设计模式之单一职责原则、开放-封闭原则、里氏替换、依赖倒置

Published: 22 Oct 2018 Category: design_pattern

一、单一职责原则(SRP)

1.1 原则内容

就一个类而言,应该仅有一个引起它变化的原因。

单一原则是多有原则中最简单的,也是最难正确运用的之一。

1.2 职责

职责即变化的原因。如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。

1.3 分离耦合的职责

一般操作就是分离接口。

二、开放-封闭原则(OCP)

2.1 内容

软件实体应该是可以扩展的,但是不可修改。 或者说对扩展开放,对修改封闭。这里的软件实体可以是类、模块、函数等等。

用好了这个原则,可以给软件带来灵活性、可用性以及可维护性。

2.2 抽象

怎么做到不改动模块源代码的情况下去更改它的行为呢?关键是抽象。

模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,所以它对于更改是可以关闭的。同时,通过从这个抽象体派生,也可以扩展此模块的功能。

一般是两种方式:将函数行为抽象到一个interface;或者把函数行为定义在一个抽象类里。

至于将那些函数行为抽象出来,要依赖经验。预测出易变的地方和各种可能性。

那如果不能预测,就要通过刺激来找出易变的地方。

2.3 刺激变化

  • 编写测试。
  • 更短的迭代周期。
  • 优先开发最重要的特性。
  • 尽早地、经常性地发布版本,尽量早地让客户接触软件,来得到反馈。

三、Liskov替换原则(LSP)

OCP背后的主要机制是抽象和多态。在Java中,支持抽象和多态的关键机制之一是继承。

LSP这种设计规则在支配者这种特殊的继承用法。

3.1 内容

子类型必须能够替换掉它们的基类型。

并不是IS-A关系。(比如正方形is a 长方形,但是在使用setHeight和setWidth时,并不能替换长方形的)

3.2 几个辨别违背OCP设计的方法

  • 子类完成的功能少于其基类地派生类通常是不能替换其基类的。
  • 在派生类的方法中添加了其基类不会抛出的异常。

对于LSP的违反也潜在地违反了OCP,LSP是使OCP成为可能得主要原则之一。正是子类型的可替换性才是的使用基类类型的模块在无需修改的情况下就可以扩展。

四、依赖倒置原则(DIP)

4.1 内容

  • 高层模块不应该依赖于低层模块,二者都应该依赖于抽象
  • 抽象不应该依赖于细节,细节应该依赖于抽象。

4.2 层次化倒置

dip 上面依赖关系是传递的,不符合依赖倒置原则。

dip 通过这种倒置的接口所有权,对于MehanismLayer或者UtilityLayer的任何改动都不会影响到PolicyLayer. 而且,PolicyLayer可以在定义了符合PolicyServiceInterface的任务上下文中重用。

这样,通过倒置这些依赖关系,我们创建了一个更灵活。更持久、更容易改变的结构。

4.3 扩展的规则

DIP包含一个启发式规则: 程序中所有依赖关系都应该终止于抽象类或者接口。

可以进行规则扩展:

  • 任何变量都不应该持有一个指向具体类的指针或者引用。
  • 任何类都不应该从具体类派生
  • 任何方法都不应该覆写它的任何基类中的已经实现了的方法。