设计模式原则之里氏替换原则
转载自:https://mp.weixin.qq.com/s/Uq4g53cQ7YKAXP8TuRV2Gw
定义:
1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
2:所有引用基类的地方必须能透明地使用其子类的对象
通俗来讲:父类必须能够使用子类替换
里氏替换原则能带来哪些好处?
-
里氏替换原则能够将对于基类中定义的所有子程序,用在它的任何一个派生类中时的含义都应该是相同的。这样继承才不会增加复杂度,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。继承带来的复杂度就降低了。
-
针对基类编程可以提高代码的复用性
如何保证遵循里氏替换原则
继承是保证里氏替换原则的前提,但是继承也有不能满足里氏替换原则的时候。此时我们可以采用如下两种方法进行设计:
1、重新提取公共部分的方法
把冲突的派生类与基类的共部分提取出来作为一个抽象基类,然后分别继承这个类。
2、改变继承关系
即:从父子关系变为委派关系或兄弟关系。
可以把它们的一些公有特性提取到一个抽象接口,再分别实现。
例如:
最初发送邮件的设计如下:
考虑到给普通人发送邮件和给VIP用户发送邮件中的send方法中的代码有重复,遵从里氏替换原则,我们将共有部分的代码提取出来,并改变CommonCustomer和VIPCustomer的继承关系。修改之后如下:
总结:
里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
-
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
-
子类中可以增加自己特有的方法。
-
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
-
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。