设计原则之里氏替换原则–子类可以替换父类吗
里氏替换原则(Liskov Substitution Principle)LSP
,这个原则是说子类应该可以替换父类进行使用。
这个原则的英文描述是functions that use pointers of references to base classes must be able to use objects of derived classes without knowing it
。子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。
为什么要使用里氏替换原则
在我们的日常开发中很常用依赖注入
,简单来说就是通过外部传入对象而不是内部new
对象。传入参数的时候我们可以通过标识父类或者接口。
function demo(Idemo $demo) {
$demo->run();
}
在这个函数中,我不关心你传进来的是个什么玩意,只要你实现了Idemo这个接口的对象就可以。或者是继承了Idemo这个类的自类对象也可以,只要你实现了run这个方法,并且属于Idemo这个类或者接口。我们经常使用这个方法来增加程序的测试行,扩展性,灵活性。比如我们需要一个支付接口的时候。
function buy(Payment $payment) {
$payment->pay();
}
我们购买东西的时候,只要知道我要支付就可以了,至于你传进来的是支付宝支付还是微信支付我不需要知道。
在这里面,支付宝或者微信支付就是具体的自类,而Payment
就是他们的父类。这些子类对象可以替换他们的父类对象,并且保证原来程序的逻辑行为不变及正确性不被破坏。
里氏替换和多态
其实我们上面使用的就是面向对象里面的多态
。但是多态并不是里氏替换。类的多态特性允许我们重新实现父类的函数,我们可以根据不同的需求来改写。但是里氏替换原则要求不能修改原来的逻辑行为和正确性。
比如父类中这个函数返回了异常而子类没有,那么这就违反了里氏替换原则。
比如原来内容是123,而子类改成了456,那么同样违反了里氏替换原则。
参考资料:
- 大话设计模式
- 极客时间设计模式之美