1.单一指责原则(Single Responsibility Principle)
单一职责原则主要是指 类的职责要单一,不能将太多的职责放在一个类中(高内聚、低耦合)。简单来说就是不同的功能封装在不同的类中,使用的时候提供接口就可以了。
定义:
一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中,即又定义有且仅有一个原因使类变更。
由来:
类A负责两个职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类A时,有可能会导致原本运行正常的职责P2功能发生故障。
解决方案:
分别建立两个类:A1和A2,使得A1完成职责P1,A2完成职责P2。这样修改类A1或者A2时都不会相互影响。
e.g.
在开发过程中,我们自然地将model传给Cell,然后让cell解析Model去渲染视图,并且感觉没有什么不妥,美其曰“Cell的封装”。但是这已经违背了SRP的原则,Cell的职责是描述与渲染自身,解析Model这个职责不属于Cell,并且在Cell中引入Model会增加不必要的依赖,Cell需要根据Model的改变而做出相应的修改,不利于Cell的复用。
2.里式替换原则(Liskov Substitution Principle)
定义:
- 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换成o2时,程序的行为不发生任何变化,那么T2为T1的子类。
- 定义2:所有引用父类的地方都必须能够透明地使用其子类对象。
定义解读:
两个定义所表达的意思都相同,就是在所有父类出现的地方,子类都可以出现,并且将父类对象替换为子类对象的时候,程序不会抛出任何异常或者错误,因此我们需要注意的是,尽量不要重载或者重写父类的方法(抽象方法除外),因为这样可能会改变父类原有的行为。
问题提出:
有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。
解决方案:
当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
参考链接:https://www.jianshu.com/p/8d48a550cae4
3.依赖倒置原则
定义:
- 高层模块不应该依赖低层模块,两者都应该依赖抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
依赖倒置原则的好处:
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定,降低并行开发引起的风险,提高代码的可读性和可维护性。
参考链接,里面包含例子:https://blog.csdn.net/u011857683/article/details/80287274
4.接口隔离原则(Interface Segregation Principle)
定义:
客户端不应该依赖它不需要的接口;
一个类对另一个类的依赖应该建立在最小的接口上。
定义解读:
- 一个类对另一个类的依赖应该建立在最小的接口上;
- 一个接口代表一个角色,不应该将不同的角色都交给一个接口,因为这样可能会形成一个臃肿的大接口;
- 不应该强迫客户依赖它们从来不用的方法。
优点:
使用接口隔离原则,意在设计一个短而小的接口和类,符合我们常说的高内聚低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性。
参考链接:https://www.bbsmax.com/A/nAJvqZBwzr/
5.迪米特法则(Law of Demeter)
定义:
狭义的迪米特法则定义:也叫最少知识原则(LKP,Least Knowledge Principle)。如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
广义的迪米特法则定义:一个模块设计得好坏的一个重要的标志就是该模块在多大的程度上将自己的内部数据与实现有关的细节隐藏起来。信息的隐藏非常重要的原因在于,它可以使各个子系统之间脱耦,从而允许它们独立地被开发、优化、使用阅读以及修改。
问题提出:
类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:
使用迪米特法则,降低类与类之间的耦合。
参考链接:https://blog.csdn.net/allison162004/article/details/25002541
6.开闭原则
定义:
一个软件实体(如类、模块、函数)应当对扩展开放,对修改关闭。
定义解读:
在项目开发的时候,都不能指望需求是确定不变化的,大部分情况下,需求是变化的。那么如何应对需求变化的情况?这就是开放-关闭原则要谈的。
开放-封闭原则的思想就是设计的时候,尽量让设计的类做好后就不再修改,如果有新的需求,通过新加类的方式来满足,而不去修改现有的类(代码)。那么在实际的项目开发中,是否能做到绝对的对修改关闭呢?答案一般也是否定的。既然这样,那么就要求我们在开发前,去找出变化点,然后针对变化点构造抽象,隔离出这些变化。由此可见,实现开闭原则关键是抽象。
优点:
- 具有灵活性,通过拓展一个功能模块即可实现功能的扩充,不需修改内部代码。
- 具有稳定性,表现在基本功能类不允许被修改,使得被破坏的程度大大下降