一: 单一职责原则(Single Responsibility Principle)
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
遵循单一职责的优点有:
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
二:里氏替换原则(Liskov Substitution Principle)
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
里氏替换原则的核心原理是抽象,抽象又依赖于继承这个特性,在OOP中,继承的优缺点相当明显,优点如下:
(1)代码重用,减少创建类成本,每个子类拥有父类的属性和方法;
(2)子类和父类基本相似,但又与父类有所区别;
(3)提高代码的可拓展性。
继承的缺点:
(1)继承是侵入性的,只要继承就必须拥有父类的所有属性和方法;
(2)可能造成子类代码的冗余、灵活性降低,因为子类必须拥有父类的属性和方法。
开闭原则和里氏替换原则往往是生死相依、不离不弃的,通过里氏替换来达到对扩展的开放,对修改的关闭效果。
三: 开放封闭原则(Open Close Principle)
定义:类、模块、函数等应该是可以拓展的,但是不可修改。
开闭原则指导我们,当软件需要变化时,应该尽量通过拓展的方式来实现变化,而不是通过修改已有代码来实现。这里的“应该尽量”4个字说明OCP原则并不是说绝对不可以修改原始类的。当我们嗅到原来的代码“腐化气味”时,应该尽早地重构,以便使代码恢复到正常的“进化”过程,而不是通过集成等方式添加新的实现,这会导致类型的膨胀以及历史遗留代码的冗余。因此,在开发过程中需要自己结合具体情况进行考量,是通过修改旧代码还是通过继承使得软件系统更稳定、更灵活,在保证去除“代码腐化”的同时,也保证原有模块的正确性。
四: 依赖倒置原则(Dependence Inversion Principle)
注:关系到系统的可拓展性、拥抱变化的能力、开闭原则
定义:高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
java中抽象指接口或抽象类,两者都不能直接被实例化的;细节就是实现类,实现接口或者集成抽象类而产生的也就细节,也就是可以可以加上一个 关键字new产生的对象。高层模块就是调用端,低层模块就是具体实现类。依赖倒置原则在java中表现就是,模块间依赖通过抽象发生,实现类之间不发生直接依赖关系,其依赖关系是通过接口或者抽象类产生的。如果类与类直接依赖细节,那么久会直接耦合。如此一来当修改时,就会同时修改依赖者代码,这样限制了可拓展性。
在实际编程中,我们一般需要做到如下3点:
- 低层模块尽量都要有抽象类或接口,或者两者都有。
- 变量的声明类型尽量是抽象类或接口。
- 使用继承时遵循里氏替换原则。
依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。
五: 接口隔离原则(InterfaceSegregation Principles)
注:最小化, 减少依赖从而降低变更的风险。
定义:一个类对另一个类的依赖应该建立在最小的接口上。
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建。
采用接口隔离原则对接口进行约束时,要注意以下几点:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。
六:迪米特原则(Law of Demeter)也称最少知识原则
注:通过引入一个合理的第三者降低现有对象之间的耦合度。
定义:一个软件实体应当尽可能少地与其他实体发生相互作用。
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。
一个类应该对自己需要耦合或者调用的类知道最少, 类的内部如何实现与调用者或者依赖关系越密切,耦合度越大,当一个类发生变化时,对另一个类的影响也越大。
(1)在类的划分上,应当尽量创建松耦合的类。类之间的耦合度约低,就越有利于服用。一个处于松耦合中的类一旦被修改,则不会对关联的类造成太大的波及。
(2)在类的机构设计上, 每一个类都应当尽量降低其成员变量和成员函数的访问权限。
(3)在对其他类的引用上, 一个类对其他对象的引用应当降到最低。