1.单一职责原则
定义:一个类只负责一项职责。
问题由来:一个类T有两个职责P1和P2,当修改职责P1的时候,有可能会导致原本正常的P2也发生故障。
解决方案:遵循单一职责原则,建立类T1和类T2,分别完成职责P1和职责P2。
单一职责原则,即便对于新手程序员,也是很容易遵守的。但是为什么会出现违背这一原则的情况出现呢?原因是有职责扩散。职责扩散就是,由于某种原因,职责P被分为粒度更细的P1和P2。出现这种情况时,可能把类T分解为T1和T2的成本比较高,这就违背了单一职责原则。
只要是模块化的设计,都需要遵循单一职责原则。
优点:
1.降低类的复杂度;
2.提高可读性和可维护性;
3.降低变更引发的风险。
2.里氏替换原则
定义:子类型必须能够替换掉它们的父类型。
问题由来:类A完成P1功能。现在需要对P1功能进行扩展,新功能P有P1和P2两个功能。新功能P由A的子类完成,则子类B完成P2的时候,有可能使原先的P1发生故障(由于重写了父类的方法)。
解决方案:类B尽量不要出现与父类A中重名的方法。父类A中的方法很可能带有virtual关键字,如果这是,子类出现于父类重名的方法,那么很有可能在使用子类替代父类时,出现了多态,也就是父类对象执行的是子类的方法。
通俗点说:在软件里面,把所有的父类都替换成它的子类,程序的行为没有发生任何变化。举个例子,企鹅不能是鸟的子类,因为当把程序里鸟都替换成企鹅是,程序的行为会出错,因为企鹅没有“Fly”这个功能。
里氏替换原则通俗来说就是:子类可以扩展父类的功能,但不能改变父类原有的功能;
1.子类可以实现父类中的抽象方法,但不能覆盖父类的非抽象方法;
2.子类中可以增加自己特有的方法;
3.当子类的方法重写了父类的方法时,方法的形参要比父类的宽松;
4.当子类的方法实现了父类的抽象方法时,方法的返回值要更加的严格。
3.依赖倒转原则
4.接口隔离原则
1.接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
2.为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
3.提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
5.迪米特法则
定义:一个对象应该对其他的对象保持最少的了解。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的改变也就越大。
解决方案:降低类与类之间的耦合。
迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。
6.开放封闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。
解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。