整洁架构SOLID-里氏替换原则(LSP)-LSP继承实践

正例

假设我们有一个License类,其结构如下图所示。该类中有一个名为calcFee()的方法,该方法将由Billing应用程序来调用。而License类有两个“子类型”:PersonalLicense与BusinessLicense,这两个类会用不同的算法来计算授权费用。

在这里插入图片描述

上述设计是符合LSP原则的,因为Billing应用程序的行为并不依赖于其使用的任何一个衍生类。也就是说,这两个衍生类的对象都是可以用来替换License类对象的。

反例

正方形/长方形问题是一个著名的违反LSP的设计案例,结构图如下所示:
在这里插入图片描述

在这个案例中,Square类并不是Rectangle类的子类型,因为Rectangle类的高和宽可以分别修改,而Square类的高和宽则必须一同修改。由于User类始终认为自己在操作Rectangle类,因此会带来一些混淆。例如在下面的代码中:

Rectangle r = …r.setW(5);
r.setW(5);

r.setH(2);
assert(r.area()== 10);

很显然,如果上述代码在…处返回的是Square类,则最后的这个assert是不会成立的。

如果想要防范这种违反LSP的行为,唯一的办法就是在User类中增加用于区分Rectangle和Square的检测逻辑(例如增加if语句)。但这样一来,User类的行为又将依赖于它所使用的类,这两个类就不能互相替换了。

上一篇:Python库 - Scrapy


下一篇:Jupyter Notebook 使用教程