《架构整洁之道》第 9 章 LSP:里氏替换原则

均为原创,读架构整洁之道的笔记。

包含了部分自己的理解,包含了原书中至少70%的知识点。
完整笔记,各位老哥友链加起来吧。
我的博客地址:www.yuque.com/_huangkuan


里氏替换原则:(LSP :Liskov Substitution Principle)。

使用一个父类对象,替换成该父类对象的子类对象后,该程序不会发生异常。(该书指的为接口,而没有提到继承关系)

或者说,调用一个Interface,切换成直接调用该接口的实现对象后,该程序不会发生异常。(该书中的表述为接口)

继承的使用指导

场景

Billing调用License,获取授权费用。License接口有两个实现类。这两个实现类中计算授权费用的规则不一样,但是业务是一样的。按照业务切换实现类,业务是可以正常进行的,不会破坏程序的正确性,不会发生异常。最关键的是这两个实现类,可以直接替换掉**License**接口。这样就是符合LSP原则的。

《架构整洁之道》第 9 章 LSP:里氏替换原则

正方形/长方形问题

以下设计中,正方形/长方形问题,是一个著名的违反LSP的设计案例。

《架构整洁之道》第 9 章 LSP:里氏替换原则

可以看到,User调用Rectangle为获得长方形的面积,可设置宽高。而正方形与长方形的设置宽高的逻辑并不一致,所以正方形错误的继承了Rectangle。如果使用Square,来替换掉Rectangle,就会发现错误。看下面的例子。

Rectangle r = ... //当这里是长方形时Rectangle,这个断言自然能通过。但是
  //如果切换成正方形Square时,这个断言是通过不了的。
r.setW(5);
r.setH(2);
assert(r.area()==10);

即可以确认,子类型,并不能完全替代其父类,会发生逻辑上的问题。所以这是一个违反LSP的案例,正方形不该继承于或者说成为长方形的子类型。

要想防范这种LSP的行为,唯一的办法就是在User类中增加用于区分RectangleSquare的检测逻辑,如if语句,但是这就造成了强依赖,使用者强烈依赖被使用者。

LSP 与软件架构

可以看出,上述讲的是类和接口的继承与实现关系。然而随着时间推移,LSP演变成了一种更广泛的,指导接口与其实现方式的设计原则。

违反 LSP 的案例

书中举的是一个出租车调度服务程序,面向多个出租车公司,用户发出请求,由调度服务运算选择出租车公司中的某一辆车,但是其中有一家公司的调用方式,和其他公司不一样,所以很难做切换和统一。

面对系统要向多个第三方提供服务,接口设计应当在调用方式和存储上,统一格式,并能严格区分和识别流量。使其在切换调用第三方时,代码不用做改动。这里将第三方看作是可替换的组件。

本章小结

LSP可以且应该被用于软件架构层面,因为一旦违反了可替换性,该系统就不得不为此增添复杂的应对机制。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!