设计模式之禅阅读笔记之6大设计原则

一、设计模式之单一之责原则

  1. 定义

    单一之责原则的定义是:有且仅有一个原因引起类或接口的变更。

  2. 反例

    电话通话有4个过程:拨号、通话、回应、挂断,代码实现如下:

    public interface IPhone {
      // 拨通电话
      void dial();
      // 通话
      void chat();
      // 通话完毕、挂断电话
      void hangup();
    }
    
  3. 单例模式改造

    public interface IConnectionManager {
      // 拨通电话
      void dial();
      // 通话完毕、挂断电话
      void hangup();
    }
    public interface IDataTransfer {
      // 通话
      void chat(IConnectionManager m);
    }
    // 同时实现IConnectionManager和IDataTransfer
    public Phone implements IConnectionManager,IDataTransfer {}
    

二、设计模式之里式替换原则

  1. 定义

    里式替换原则定义为:只要是父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误和异常,但是有子类出现的地方,父类不一定能适应。该定义指出了在使用继承时的四个规范:

    1. 子类必须完全实现父类的方法,如果子类不能完整的实现父类的方法,则应该断开父子继承关系。
    2. 子类可以有自己的个性,子类在继承时可以添加父类没有的方法,即子类能使用的地方,父类不一定能使用。
    3. 覆盖或实现父类的方法时输入参数可以被放大,子类可以重载父类的方法,重载方式为扩大参数的类型。
    4. 覆盖或实现父类的方法时输出结果可以被缩小,即父类的一个方法的返回值类型必须宽于子类覆写或重载该方法时的返回值类型。

三、依赖倒置原则

  1. 定义

    依赖倒置原则的定义为:

    1. 模块间的依赖通过抽象发生,实现类直接不发生直接的依赖关系,其依赖关系通过接口或抽象类产生

    2. 接口或抽象类不依赖于实现类

    3. 实现类依赖接口或抽象类

    即”面向接口编程“。

  2. 对象依赖关系的传递方式

    1. 构造函数传递依赖对象

      public interface IDriver{
        void driver();
      }
      public interface ICar{
        void run();
      }
      public class Driver implements IDriver {
        private ICar car;
        public Driver(ICar car) {
          this.car = car;
        }
      }
      
    2. Setter方法传递依赖对象

      public interface IDriver{
        void driver();
      }
      public interface ICar{
        void run();
      }
      public class Driver implements IDriver {
        private ICar car;
        public Driver() {
         
        }
        public void setCar(ICar car) {
          this.car = car;
        }
      }
      
    3. 接口声明依赖对象

      public interface IDriver{
        void driver(ICar icar);
      }
      public interface ICar{
        void run();
      }
      public class Driver implements IDriver {
        public Driver() {
        }
        public void driver(ICar icar) {
          // ...
        }
      }
      
  3. 使用原则

    1. 每个类尽量都有接口或抽象类。
    2. 变量的表面类型尽量是接口或抽象类。
    3. 任何类都不应从具体类派生。
    4. 尽量不要覆写父类已实现的方法。
    5. 结合里式替换原则使用。

四、接口隔离原则

  1. 定义

    接口隔离的原则的定义为:客户端不应该依赖它不需要的接口;类间的依赖应该建立在最小接口上。

    概括为一句话为:建立单一接口,不要建立臃肿的接口,接口尽量细化,同时接口中的方法要尽量少。

  2. 与单一之责原则的区别

    单一之责原则注重的是类或接口的之责,是业务逻辑上的划分;而接口隔离原则要求接口尽量细化,即对于一个接口而言,客户端不需要的方法就不应该声明在该接口中(即使该方法和其他方法为同一职责),应拆分成多个接口提供给对应的客户端使用。

    注:根据接口隔离原则拆分接口时,首先必须满足单一职责原则。

  3. 接口隔离原则要求接口要高内聚,具体为接口应该尽量少的公布public方法,减少对外的交互。

五、迪米特法则

  1. 定义

    迪米特法则又称为最少知识原则。一个对象应该对其他对象有最少的了解,通俗的讲,一个类应该对自己需要耦合或调用的类指定得最少,你的内部有多复杂我不需要知道,我就知道你提供的这么多public方法。

  2. 朋友类的定义:出现在成员变量,方法的输入输出的类成为朋友类,迪米特法则要求一个类只和朋友类交流(除了jdk和一些第三方库提供的api),同时和朋友类间的依赖不能过度耦合,即朋友类应该提供最少的Public方法。

接口隔离原则和迪米特法合起来为高内聚低耦合。

六、开闭原则

  1. 定义

    开闭原则的定义为:一个类、模块、函数对扩展开房,对修改关闭。即通过扩展实现业务的变化,而不应该修改现有类的代码。

  2. 代码示例:书店销售书籍为例

    public interface IBook {
      // 书籍名称
      String getName();
      // 获取书籍价格,在非金融类项目中对货币处理时,一般取两位精度,计算式扩大100倍,展示时缩小100倍。
      int getPrice();
      // 作者
      String getAuthor();
    }
    public class NovelBook implements IBook {
      private String name;
      private String price;
      private String author;
      // 全参构造方法
      // 实现接口中的get方法...
    }
    public class BookStore {
      private final static ArrayList<IBook> bookList = new ArrayList<>;
      static {
        bookList.add(NovelBook("天龙八部", 3200, "金庸"));
        bookList.add(NovelBook("巴黎圣母院", 5600, "雨果"));
        bookList.add(NovelBook("西游记", 4300, "吴承恩"));
      }
      
      public static void main(String[] args) {
        // 卖书...
      }
    }
    

    业务变化:40元以上的书籍9折销售,

    按照开闭原则,应该增加一个IBook的实现类OffNovelBook,覆写getPrice方法,BookStore通过使用OffNovelBook类来实现业务变化,而不是修改接口或者修改NovelBook类的代码。

posted @ 2022-07-02 21:15  我爱这世间美貌女子  阅读(30)  评论(0编辑  收藏  举报