Java-第十八部分-设计模式-七大设计原则

215 阅读5分钟

设计模式全文

七大原则

  • 设计模式的依据
  • 核心思想
  1. 找出应用中可能需要变化的地方,将它们独立出来,不和那些不需要变化的代码混在一起
  2. 针对接口编程,而不是针对实现编程
  3. 为了交互对象之间的松耦合

单一职责原则

  • Single Responsibility Principle
  • 对类来说,一个类只负责一项原则
  • 体现各行其职
  • 降低类的复杂度,达到一个类只负责一项职责,降低变更带来的风险
  • 类中代码比较少,也可以在方法级别上遵守单一原则
  • 交通工具的运行案例

类上遵守

class RoadVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " is run in the road...");
    }
}
class SkyVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " is run in the sky...");
    }
}
class SeaVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " is run in the sea...");
    }
}

方法上遵守

class VehicleSR {
    public void runRoad(String vehicle) {
        System.out.println(vehicle + " is run in the road...");
    }
    public void runSky(String vehicle) {
        System.out.println(vehicle + " is run in the sky...");
    }
    public void runSea(String vehicle) {
        System.out.println(vehicle + " is run in the sea...");
    }
}

接口隔离原则

  • Interface Segregation Principle
  • 客户端不应该依赖他不需要的接口,即一个类对另一个类的依赖,应该建立在最小的接口
  • 一个类所依赖的类,要求是使用到该类所实现的对象的所有方法,没有方法是实现了,却用不到的
  • 案例,B和D多实现了几个方法,要将Interface1拆成两个接口,让A和C与需要的接口建立以来即可 demo.png
  • 接口隔离处理 demo2.png

依赖倒转(倒置)原则

  • Dependence Inversion Principle
  1. 高层模块不应该依赖底层模块,二者都应该依赖其抽象
  2. 抽象不应该依赖细节,细节应该依赖抽象
  3. 面向接口编程
  4. 抽象的东西要稳定
  5. 抽象类制定好规范,不涉及具体的操作,展现细节的任务交给实现类完成
  • 为使用层和实际资源增加一个缓冲层,增加可扩展性,扩展时,先修改底层资源(接口);使用层依赖于接口,可以不断优化具体实现
  • 使用类Person依赖接口,并不直接依赖实现类
interface IReceiver {
    String getInfo();
}
class Email implements IReceiver {
    public String getInfo() {
        return "hello, world";
    }
}
class Wechat implements IReceiver {
    public String getInfo() {
        return "weChat";
    }
}
class Person {
    public void receive(IReceiver iReceiver) {
        System.out.println(iReceiver.getInfo());
    }
}

传递的三种方式

  • 接口传递
  • 构造传递
class Person {
    IReceiver ir;
    public Person(IReceiver ir) {
        this.ir = ir;
    }
    public void receive() {
        System.out.println(ir.getInfo());
    }
}
//使用
Person person = new Person(new Email());
person.receive();
  • setter传递
interface IPerson {
    void receive();
    void setIr(IReceiver ir);
}
interface IReceiver {
    String getInfo();
}
class Email implements IReceiver {
    public String getInfo() {
        return "hello, world";
    }
}
class Wechat implements IReceiver {
    public String getInfo() {
        return "weChat";
    }
}
class Person implements IPerson {
    IReceiver ir;
    public void receive() {
        System.out.println(ir.getInfo());
    }
    public void setIr(IReceiver ir) {
        this.ir = ir;
    }
}

//使用
Person person = new Person();
person.setIr(new Wechat());
person.receive();

注意事项

  • 低层模块尽量都要有抽象类或接口,稳定性更好
  • 变量的声明类型尽量是抽象类或接口,在实际的变量引用和实际对象间,存在一个缓冲层,利于程序拓展和优化
  • 继承时要遵循里氏替换原则

里氏替换原则

  • Likov Substitution Principle
  • 父类中凡是已经实现好的方法,实际上是设定规范和契约,虽然不强制所有子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,那么就会对整个继承体系造成破环
  • 继承存在弊端,使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他类所继承,当这个类修改时,必须考虑所有子类
  • 继承的原则
  1. 如果对每个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序P在所有的对象O1都代换成O2时,程序P的行为没有发生改变,那么T2是T1的子类型
  2. 所有引用基类的地方必须能透明地使用其子类对象
  3. 子类中尽量不要重写父类方法,如果子类大面积地重写了父类的方法,那么就没有继承的必要了
  4. 继承让两个类耦合增强了,适当情况下,可以通过聚合、组合、依赖来解决问题
  • B类需要重写A的方法,可以将AB提出一个基类,让B与A组合 demo.png

开闭原则ocp

  • Open Closed Principle,核心,基础,重要
  • 类、模块和函数应该对扩展(对提供功能方)开放,对修改(对使用方)关闭,用抽象构建框架,用实现扩展细节
  • 当软件需要变化时,通过扩展软件实体的行为来实现变化,不通过修改已有的代码
  • 强调代码的拓展性,如果需要增加一个绘画形状,只需要新增一个图形继承Shape
//使用方依赖抽象,尽量简单
class GraphicEditor {
    public void draw (Shape s) {
        s.draw();
    }
}
abstract class Shape {
    int m_type;
    abstract void draw();
}
class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }
    void draw() {
        System.out.println("矩形");
    }
}
class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }
    void draw() {
        System.out.println("圆形");
    }
}
class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }
    void draw() {
        System.out.println("三角形");
    }
}

迪米特法则

  • Demeter Principle,最少知道原则,只与直接的朋友通信
  1. 直接的朋友,每个对象都会其他对象有耦合关系,只要两个对象之间有耦合关系,那么就是朋友关系,依赖、关联、组合和聚合等
  2. 其中出现的成员变量,方法参数,方法返回值中的类为直接的朋友,而局部变量中的类不是直接朋友
  3. 陌生的类,最好不要以局部变量的形式出现
  • 一个对象应该对其他对象保持最少的了解
  • 类与类关系越密切,耦合度越大
  • 一个类对自己依赖的类知道的越少越好,不管被依赖的类多复杂,都将逻辑分装在类的内部,对外只提供构造方法
  • 一个类的行为要在本类中实现,不要再其他类中实现

细节

  • 核心是降低类与类之间的耦合
  • 每个类都减少了不必要的依赖,只是要求降低类之间的耦合关系,并不是完全没有依赖

合成复用原则

  • Composite Reuse Principle
  • 尽量使用合成/聚合的方式,而不使用继承
  • 如果只是为了让B类使用A类的方法,而让B去继承A,会让AB的耦合性增强
  • 要倾向于has a,避免is a demo.png