设计模式---六大设计原则

时间:2022-09-20 00:41:24

六大设计原则

  1. 单一职责原则
  2. 接口隔离原则
  3. 开闭原则
  4. 依赖倒置原则
  5. 里氏代换原则
  6. 迪米特法则

单一职责原则

我们分别看两个案例,一个是遵守单一职责原则,另一个是违背。

违背的案例

class Computer {
    void calc() {
        System.out.println("计算数据"); // 基本功能,么得问题
    }
    void display() {
        System.out.println("显示计算结果"); // 现在的计算机确实有显示功能
    }
    void run() {
        System.out.println("以百米冲刺的速度奔跑"); // 这什么玩意儿?这个类到底是干嘛的
    }
}

遵守的案例

class Computer {
    void calc() {
        System.out.println("计算数据"); // 基本功能,么得问题
    }
    void display() {
        System.out.println("显示计算结果"); // 现在的计算机确实有显示功能
    }
}
class Humam {
    void run() {
        System.out.println("以百米冲刺的速度奔跑"); // 人会跑不是很正常嘛
    }
}

单一职责的核心:限制类的职责范围,杜绝功能复杂的类的产生
接口隔离原则也是同样的思想,就不废话了。

开闭原则

class Style {
    public void set() {
        System.out.println("设置圆角");
    }
}

当需要改变样式的时候。不遵守开闭原则的做法。

class Style {
    public void set() {
        // System.out.println("设置圆角");
        System.out.println("设置order");
        /* 
        	直接修改原有的方法上做修改
         */
    }
}

而遵守开闭原则的做法。

// 将原有的Style类抽象成接口,这样对客户端也没有影响,
// 因为用的还是Style并没有改名,只是原来是个类,现在变成了接口
interface Style {
    void set();
}
class Radius implements Style {
    public void set() {
        System.out.println("设置圆角");
    }
}
class Order implements Style { // 不对原有的实现类修改,而是增加一个新个实现类
    public void set() {
         System.out.println("设置order");
    }
}

开闭原则的核心:对修改关闭,对拓展开放
不在原有的代码上增减新的代码,而是添加新的模块。核心要点是面向接口编程。

依赖倒置原则

不符合依赖倒置原则的案例。

class Radius {
    public void set() {
        System.out.println("设置圆角");
    }
}
class Order {
    public void set() {
        System.out.println("设置order");
    }
}
class Client {
    public void setRadius(Radius radius) {
        adius.set();
    }
    public void setOrder(Order order) {
        rder.set();
    }
}

符合依赖倒置原则的案例。

interface Style {
    void set();
}
class Radius implements Style {
    public void set() {
        System.out.println("设置圆角");
    }
}
class Order implements Style {
    public void set() {
        System.out.println("设置order");
    }
}
class Client {
    public void setStyle(Style style) {
        style.set();
    }
}

依赖倒置的核心:从依赖具体类变为依赖抽象或接口。面向接口编程。

里氏代换原则

不符合里氏代换原则的案例。

class CacheCard {
    protected int balance;
    public void peek() {
        System.out.println("余额:" + balance);
    }
    public void deposit(int num) {
        balance += num;
        System.out.println("存款金额:" + num);
        peek();
    }
    public void withdraw(int num) {
        balance += num;
        System.out.println("取款金额:" + num);
        peek();
    }
}
class CreditCard extends CacheCard {
    public void deposit(int num) { // 信用卡并没有存钱这个功能,不应该重写
        balance += num;
        System.out.println("还款金额:" + num);
        peek();
    }
    public void withdraw(int num) { // 也没有取款的功能,不应该重写
        balance += num;
        System.out.println("支付金额:" + num);
        peek();
    }
}

符合里氏代换原则的案例。

interface BankCard {
    int balance;
    default void peek() {
        System.out.println("余额:" + balance);
    }
    void positive(int num);
    void negative(int num);
}
class CacheCard implements BankCard {
    public void positive(int num) {
        balance += num;
        System.out.println("存款金额:" + num);
        peek();
    }
    public void negative(int num) {
        balance -= num;
        System.out.println("取款金额:" + num);
        peek();
    }
}
class CreditCard implements BankCard {
    public void positive(int num) {
        balance += num;
        System.out.println("还款金额:" + num);
        peek();
    }
    public void negative(int num) {
        balance -= num;
        System.out.println("支付金额:" + num);
        peek();
    }
}

里氏代换原则的核心思想:使用父类能够实现的功能,使用其子类依旧能实现。限制方法重写的范围,从业务的角度出发我们只可以重写父类中被允许重写的方法,而不是从Java语法角度(那能重写的多了去了)出发重写方法。

迪米特法则

不符合迪米特法则的案例。

class Student {
    String name;
    String sex;
    int score;
}
class Teacher {
    String name;
    String sex;
    Student[] students;
    int max() {
        int res = 0;
        for (student : students) {
            res = Math.max(res, student.score);
        }
        return res;
    }
    int min() {
        int res = 0;
        for (student : students) {
            res = Math.min(res, student.score);
        }
        return res;
    }
}
class President {
    String name;
    String sex;
    Student[] students; // 不应该依赖Student类,而应该依赖Teacher类,将所有对于students的操作封装到Teacher类中
    Teacher[] teachers;
    int avg() { // 这个方法应该在Teacher中定义
        int res = 0;
        for (student : students) {
            res += student.score;
        }
        return res / students.length;
    }
    String[] teachersName() { // 获取所有的老师名字
        String[] res = new String[teachers.length];
        for (int i = 0; i < res.length; i ++) {
            res[i] = teachers[i].name;
        }
        return res;
    }
}

符合迪米特法则的案例。

class Student {
    String name;
    String sex;
    int score;
}
class Teacher {
    String name;
    String sex;
    Student[] students;
    int max() {
        int res = 0;
        for (student : students) {
            res = Math.max(res, student.score);
        }
        return res;
    }
    int min() {
        int res = 0;
        for (student : students) {
            res = Math.min(res, student.score);
        }
        return res;
    }
    int avg() { // 这个方法应该在Teacher中定义
        int res = 0;
        for (student : students) {
            res += student.score;
        }
        return res / students.length;
    }
}
class President {
    String name;
    String sex;
    Teacher[] teacher; // 依赖Teacher类
    int[] avgs() { // 获取每个班级的平均分
        int[] res = new int[teacher.length];
        for (int i = 0; i < res.length; i ++) {
            res[i] = teacher[i].avg(); // 实际计算调用Teacher内的计算
        }
        return res;
    }
    String[] teachersName() { // 获取所有的老师名字
        String[] res = new String[teachers.length];
        for (int i = 0; i < res.length; i ++) {
            res[i] = teachers[i].name;
        }
        return res;
    }
}

迪米特法则的核心思想:最少知道,最少依赖。类的定义应当把对于其他类的依赖降到最低。
遵守迪米特法则的同时也基本满足了单一职责原则。