前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《架构整洁之道》第 9 章 LSP:里氏替换原则

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

原创
作者头像
巴啦啦的积累
发布2023-05-25 13:50:55
2680
发布2023-05-25 13:50:55
举报
文章被收录于专栏:巴啦啦的积累

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

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

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

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

继承的使用指导

场景

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

正方形/长方形问题

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

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

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

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

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

LSP 与软件架构

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

违反 LSP 的案例

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

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

本章小结

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 继承的使用指导
    • 场景
      • 正方形/长方形问题
      • LSP 与软件架构
      • 违反 LSP 的案例
      • 本章小结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档