一:单一职责原则,缩写SRP(Single Responsibility Principle)
定义:仅有一个导致类变化的原因。
举个列子
类O,有两个不同的职责P1、P2,修改了P1,可能导致P2也跟着变化。
为了解决以上问题,我们遵照单一职责原则,做如下优化
建立两个类O1、O2,O1负责职责P1的功能,O2负责职责P2的功能。
这样,类O1和O2分别负责不同的职责,即便修改O1,也不会影响O2,同理,修改O2,也不影响O1。
在实际应用中,如何划分一个类,一个函数的职责,每个人都有自己不同的看法,具体情况根据个人经验、业务逻辑、实际需求及后续需求而定。但我们应该遵照一个基本指导原则:
完全不同的功能不应该放在一个类中。
二:里氏替换原则,缩写LSP(Liskov Substitution Principle)
定义1:如果对每一个类型为S的对象O1,都有类型为T的对象O2,使得以T定义的所有程序P在所有的对象 O1都代换成O2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。
看完之后,整个人都不好了~~
我们换个更直截了当的定义:
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
举个例子
功能P1,由T1类完成,现在功能P1需要扩展,建立T2类,继承T1类,在T2类完成扩展时,可能造成原有功能P1出现问题。
所以,遵照此原则,我们在扩展时,T2类继承T1,除添加扩展功能外,尽量不重写和重载T1的方法。
但其实在现实中,常常会违背这个原则,比如我们在Android开发中自定义View。
三:依赖倒置原则,缩写DIP(Dependence Inversion Principle)
定义:抽象不应该依赖于细节,细节应当依赖于抽象。通俗点就是要针对接口编程,而不是针对实现编程。
举个例子
类T依赖类O2,现在类T需要改为依赖类O3,则必须修改类T完成。
遵照此原则,我们修改一下为
类O2,O3实现接口I,T通过接口I与O2、O3发生联系。
依赖倒置原则的核心就是要我们面向接口编程。
四:接口隔离原则,缩写ISP(InterfaceSegregation Principle)
定义1:客户端不应该依赖它不需要的接口。
另一种定义
定义2:类间的依赖关系应该建立在最小的接口上。
接口隔离原则将非常庞大、臃肿的接口拆分成更小的和更具体的接口,这样客户将会只需要知道他们感兴趣的方法。
举个例子
接口I有方法M1,M2, M3。类O1实现接口I,需要接口I中的M1方法,类O2实现接口I,需要接口I中的方法M2,M3。
是不是发现对于类O1和O2来讲,接口I中的一些方法对彼此是没有用的?那么根据此原则,我们应该修正为:
将接口I拆分为I1,I2,I1中含方法M1,I2中含方法M2,M3,O1实现接口I1,O2实现接口I2。
将臃肿的接口拆分为更细粒度的接口中,使我们的系统具有更低的耦合性,提高灵活性。
五:迪米特原则,缩写LOD(Least Knowledge Principle)
定义:一个对象应该对其他对象保持最少的了解。
迪米特法则还有一个更简单的定义:只与直接的朋友通信。什么是朋友?每个对象与其他对象的耦合(组合、聚合、依赖等),我们就认定这两个对象为朋友关系。
通俗点讲,一个类对自己需要依赖的类知道的越少越好,类的内部实现跟调用者没有关系,调用者只需要知道它需要的方法即可。
类与类之间,耦合越大,修改的影响就越大,风险也就越大。所以我们应该尽量降低类与类之间的耦合,防止它们的朋友关系太铁~
六:开闭原则,缩写OCP(Open Close Principle)
定义:一个实体(类、模块、函数等)对于扩展开放,对于修改关闭。
在软件开发中,我们因为各种原因(需求变化、升级等)需要对原有代码进行修改时,可能会将错误的代码引入到已经测试过的旧代码中,是原来的系统出现错误。因此,当需要对原有代码进行修改时,我们应该尽量通过扩展的方式去实现,而不是修改原来的代码。
但其实在开发中,唯一不变的就是变化本身,产品需要不断升级、维护。
开闭原则是六大原则中最基础的一个,但也是让人最难做的一个,它指导我们如何建立一个稳定的、灵活的系统,告诉我们对于扩展开放,对于修改关闭。是不是感觉说的很对?但貌似什么都没说?