文章图片标题

里氏代换原则(LSP)

分类:架构设计 作者:阳光倾城 评论:0 点击: 400 次 日期:2016-08-12

从“开-闭”原则中可看出面向对象设计的重要原则是创建抽象化,并且从抽象化导出具体化。具体化可以给出不同的版本,每一个版本都给出不同的实现。

从抽象化到具体化的导出要使用继承关系和里氏代换原则(Liskove Substitution Principle,常缩写为LSP)。

里氏代换原则的定义:如果对每个类型为t1的对象o1,都有类型为t2的对象o2,使得以t1定义的所有程序p在所有的对象o1都代换成o2时,程序p的行为没有变化,那么类型t2是类型t1的子类型。

一个软件实体可以使用基类的时候,也可以使用其子类。

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

反过来不成立。

里氏代换要求凡是基类型使用的地方,子类型一定适用,因此子类型必须具备基类型的全部接口。或者说,子类型的接口必须包括全部的基类型的接口,而且还可能更宽(访问权限可以放大,不可以缩小)。

Java语言编译器对精度检查,但是不能检查准确度(与真实事物的相符合的程度)。

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

策略模式

如果有一组算法,就将每个算法封装起来,使得它们可以互换。

image

要互换,就需要将所有的具体策略角色放到一个类型等级结构中,使它们拥有共同的接口。这种互换性依赖的是对里氏代换原则的遵守:

AbstractStrategy s = new ConcreteStrategyA();

客户端依赖于基类类型,而对象的类型是具体策略类。这是具体策略角色可以“即插即用”的关键。

合成模式

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

image

 

代理模式

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

image

在代码重构的应用

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

1)创建一个新的抽象类C,作为两个具体类的超类,将A和B的共同行为移动到C中,从而解决A和B行为不完全一致的问题:

image

2)从B到A的继承关系改写成委派关系:

image

 

从抽象类继承

应当尽量从抽象类继承,而不从具体类继承。如果两个具体类A和B有继承关系,最简单的修改方案应当是建立一个抽象类C,然后让类A和类B成为抽象类C的子类。

image

子类应该具备父类所有的行为。

image




声明: 除非注明,本文属( 阳光倾城 )原创,转载请保留链接: http://www.tomrrow.com/archives-8011.html