【Java与模式】里氏代换原则(LSP)

一、什么是里氏代换原则

1.1 里氏代换原则

里氏代换原则的严格表达是:
如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。

换言之,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象和子类对象的区别。

里氏代换原则是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,基类才能真正被复用,而衍生类也才能够在基类的基础上增加新的行为。

反过来的代换不成立

必须指出的是,反过来的代换则不成立,即如果一个软件实体使用的是一个子类的话,那么它不一定使用于基类。

Java语言对里氏代换的支持

里氏代换要求凡是基类型使用的地方,子类型一定适用,因此子类必须具备及类型的全部接口,或者说,子类型的接口必须包括全部的基类型的接口,而且还有可能更宽。如果一个Java程序破坏了这一条件,Java编译器就会给出编译时期错误。

Java语言对里氏代换支持的局限

Java编译器的检查是有局限的。举例来说,描写一个物体大小的量有精度和准确度两种属性。所谓精度,就是这个量的有效数字有多少位;而所谓准确度,是这个量与真实的物体大小相符合到什么程度。一个量可以有很高的精度,但是却无法与真实物体的情况相吻合。Java语言编译器所能够检查的,仅仅是相当于精度的属性而已,它无法检查这个量与真实物体的差距。

换言之,Java编译器不能检查一个系统在实现和商业逻辑上是否满足里氏代换法则。一个著名的例子,就是“正方形类是否是长方形的子类"的问题。

二、里氏代换原则在设计模式中的体现。

策略模式

策略模式是所有的设计模式中比较易于理解的模式。策略模式讲的是:“如果有一组算法,那么就将每一个算法封装起来,是他们可以相互互换。”

封装的概念不是难理解的,而使得所有得算法可以互换,则需要将所有得具体策略角色放到一个类型等级结构中,使他们拥有共同得接口。显然这种互换性依赖得是对里氏代换原则得遵守。

合成模式

合成模式通过使用树结构描述整体与部分的关系。从而可以将单纯元素与复合元素同等看待。由于单纯元素和复合元素都是抽象元素角色的子类,因此两者都可以替代抽象元素出现在任何地方。

代理模式

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理模式能够成立的关键,就在于代理模式真实主题模式都是抽象主题角色的子类,客户端只知道抽象主题,而代理注意可以替代抽象主题出现在任何需要的地方,而将真实主题隐藏在幕后。

三、从代码重构的角度理解

里氏代换原则讲的是基类与子类的关系,只有当这种关系存在时,里氏代换关系才存在,反之则不存在。如果两个具体类A和B之间的关系违反了里氏代换原则设计,根据具体情况可以在下面两种重构方案选择一种:

  1. 创建一个新的抽象类C,作为两个具体类的超类(前面提到过这种重构方法)。将A和B的共同行为移动到C中,从而解决A和B行为不完全已知的问题。
  2. 从B到A的继承关系改为委派关系。即从“Is-A”改为“Has-A”
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值