设计原则(三):里氏替换原则

star2017 1年前 ⋅ 583 阅读

子类可替换基类

里氏替换原则:是对子类型的特别定义,可以描述为 派生类(子类)对象可以在程序中代替其基类(超类)对象。
指一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不察觉出基类对象和子类对象的区别。

里氏替换原则 要求凡是基类型使用的地方,子类型一定适用,因此子类必须具备基本类型的全部接口。或者说,子类型的接口必须包括全部的基类型的接口,而且还有可能更宽。

假设一个基类 Base ,另一个是其子类 Sub。那么一个方法如果可以接受一个基类对象 b 的话:method1(Base b),那么它必解码器可以接受一个子类对象 s,即也可以有 method1(s)。

在编译时期,Java 语言编译器会检查一个程序是否符全里氏替换,这是一个无关实现,纯语法意义上的检查。

例如子类私有化了基类的公共方法,Java 编译就会报错。这是因为客户端完全有可能调用基类的公开方法。如果以子类型代之,这个方法就不能被调用了,违反了里氏替换原则。

注意:反过来是不行的,即一个软件实体使用的是子类的话,那么它不一定适用于基类。

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

在其它设计模式中的体现

  • 策略模式:如果有一组算法,将每一种算法封装起来,使它们可以互换。封装易理解,要实现所有的算法可以互换,则需要将所有的具体策略角色放到一个类型等级结构中,使它们拥有共同的接口。这种互换性依赖的是对 里氏替换原则的遵守。

    AbstractStrategy s = new ConcreteStrategyA();
    

    上面示例可以看出,客户端依赖于基类类型,而变量的真实类型则是具体策略类。这种具体策略角色可以 即插即用(Pluggable)的关键。

  • 合成模式:通过使用树结构描述整体与部分的关系,从而可以将单纯属元素与复合元素同等看待。

    由于单纯元素和复合元素都是抽象元素角色的子类,因此两者都可以替换抽象元素出现的任何地方。

    里氏替换原则 是合成模式能够成立的基础。

  • 代理模式:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用 。

    代理模式能够成立的关键,就在于代理模式(代理对象)与真实主题模式(原对象)都是抽象主题角色的(抽象类)的子类。客户端只知道抽象类,而代理对象可以替换抽象类出现在任何需要的地方,而将真实主题隐藏在幕后。

    里氏替换原则是代理模式能够成产的基础。

从代码重构的角度理解

里氏替换原则讲的是基类与子类的关系。只有当这种关系存在时,里氏替换关系才存在;反之则不存在。

如果有两个具体类 A 和 B 之间违反了里氏替换原则的设计,则重构方案可以如下:

  1. 创建一个新的抽象类 C,作为两个具体类的基类,将 A 和 B 的共同行为移动到 C 中,从而解决 A 和 B行为不完全一致的问题。
  2. 从 B 到 A 的继承关系改写为委派关系。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: