【设计模式】设计模式-设计原则
设计模式-设计原则
1、单一原则
单一职责原则的英文名称是Single Responsibility Principle,简称SRP。单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。There should never be more than one reason for a class to change。
单一职责原则的优点有以下几个方面:
- 降低类的复杂性;-
- 提高类的可读性;
- 提高代码的可维护性和复用性;
- 降低因变更引起的风险。
2、里氏替换原则
里氏替换原则英文名称是Liskov Substitution Principle,简称LSP。里氏替换原则规定任何基类可以出现的地方,子类一定可以出现。
里氏替换原则的定义有以下两种。
第一种定义:
If for each object o1 of type S there is an object o2 of type T such that forall programs P defined in terms of S,the behavior of P is unchanged wheno1 is substituted for o2 then T is a subtype of S.
这个定义是最正宗的定义,意思是:如果对一个类型为S的对象o1,都有类型为T的对象o2,使得以S定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T是类型S的子类型。
第二种定义:
Functions that use pointers or references to base classes must be able touse objects of derived classes without knowing it.
第二个定义意思是:所有引用基类的地方必须能透明地使用其子类对象。清晰明确地说明只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道父类还是子类;但是反过来则不可以,有子类的地方,父类未必就能适应。
里氏替换原则为良好的继承定义了一个规范,它包含4层含义:
- 子类必须完全实现父类的方法;
- 子类可以有自己的个性;
- 覆盖或实现父类的方法时输入参数可以被放大;
- 覆盖或实现父类的方法时输出结果可以被缩小。
3、依赖倒置原则
依赖倒置原则英文名称是:Dependence Inversion Principle,简称DIP。
原始定义
High level modules should not depend upon low level modules. Bothshould depend upon abstractions. Abstractions should not depend upondetails. Details should depend upon abstractions.
翻译过来,包括三层含义:
- 高层模块不应该依赖低层模块,两者都依赖其抽象;
- 抽象不依赖细节;
- 细节应该依赖于抽象。
在项目中使用这个原则只要遵循以下几个规则:
- 每个类尽量都具有接口或抽象类,或者抽象类和接口两者都具备。这是依赖倒置的基本要求,接口和抽象类都是抽象的,有了抽象才可能有依赖倒置;
- 变量的表面类型尽量是接口或者是抽象类;
- 尽量不要重写基类的方法。如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要重写。类之间依赖的是抽象,重写了非抽象方法,对依赖的稳定性会产生一定的影响;
- 结合里氏替换原则使用。里氏替换原则指出父类出现的地方子类就可以出现,结合依赖倒置原则可以得出一个通俗的规则:接口负责定义抽象方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确地实现业务逻辑,同时在适当的时候对父类进行细化。
4、接口隔离原则
接口隔离原则的英文名称是:Interface Segregation Principle,简称ISP。
接口隔离原则有如下两种定义。
第一种定义:
Clients should not be forced to depend upon interfaces that they don't use.
意思是:客户端不应该依赖它不需要的接口。
第二种定义:
The dependency of one class to another one should depend on the smallest possible interface。
意思是:类间的依赖关系应该建立在最小的接口上。
接口隔离原则的具体含义如下:
- 一个类对另外一个类的依赖性应当是建立在最小的接口上的。
- 一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。因此使用多个专门的接口比使用单一的总接口要好。
- 不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构,即不要强迫客户使用它们不用的方法,否则这些客户就会面临由于这些不使用的方法的改变所带来的改变。
实践应用中可以根据以下几个规则来衡量:
- 一个接口只对一个子模块或者业务逻辑进行服务;
- 只保留接口中业务逻辑需要的public方法;
- 尽量修改污染了的接口,若修改的风险较大,则可采用适配器模式进行转化处理;
- 接口设计应因项目而异,因环境而异,不能教条照搬。
5、迪米特法则
迪米特法则英文名称是Law of Demeter,简称LoD。
迪米特法则的定义:
迪米特法则又叫最少知识原则(Least Knowledge Principle,LKP),意思是一个对象应当对其他对象尽可能少的了解。
其中具有代表性的是以下几种表述:
- 只与你直接的朋友们通信(Only talk to your immediate friends);
- 不要跟“陌生人”说话(Don't talk to strangers);
- 每一个软件单位对其他的单位都只有最少的了解,这些了解仅局限于那些与本单位密切相关的软件单位。
6、开闭原则
开闭原则的英文名称是Open-Closed Principle,简称OCP。
开闭原则的定义:
Software entities should be open for extension,but closed for modification.
意思是:一个软件实体应当对扩展开放,对修改关闭。
开闭原则的重要性可以通过以下几个方面来体现:
-
开闭原则提高复用性。在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑,代码粒度越小,被复用的可能性就越大,避免相同的逻辑重复增加。开闭原则的设计保证系统是一个在高层次上实现了复用的系统。
-
开闭原则提高可维护性。一个软件投产后,维护人员的工作不仅仅是对数据进行维护,还可能对程序进行扩展,就是扩展一个类,而不是修改一个类。开闭原则对已有软件模块,特别是最重要的抽象层模块要求不能再修改,这就使变化中的软件系统有一定的稳定性和延续性,便于系统的维护。
-
开闭原则易于测试。测试是软件开发过程中必不可少的一个环节。测试代码不仅要保证逻辑的正确性,还要保证苛刻条件(高压力、异常、错误)下不产生“有毒代码”(Poisonous Code),因此当有变化提出时,原有健壮的代码要尽量不修改,而是通过扩展来实现。否则,就需要把原有的测试过程回笼一遍,需要进行单元测试、功能测试、集成测试,甚至是验收测试。开闭原则的使用,保证软件是通过扩展来实现业务逻辑的变化,而不是修改。因此,对于新增加的类,只需新增相应的测试类,编写对应的测试方法,只要保证新增的类是正确的就可以了。