设计模式 之 里氏代换原则 (Liskov's Substitution Principle)

Motivation

动机

All the time we design a program module and we create some class hierarchies. Then we extend some classes creating some derived classes.

一直以来,我们设计程序模块,并且建立类的层次关系,然后扩展类来创建派生类。

We must make sure that the new derived classes just extend without replacing the functionality of old classes. Otherwise the new classes can produce undesired effects when they are used in existing program modules.

我们必须保证新派生的类只是扩展,而没有替换旧类中的功能。否则当新类用在已有程序模块中时将可能产生不期望的影响。

Likov‘s Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.

里氏代换原则要求如果一个程序模块使用了基类,那么对基类的引用能够使用派生类替代,并且不会影响程序模块的功能。

Intent

目的

Derived types must be completely substitutable for their base types.

派生类型必须可以完全替代它们的基类型。

Example

示例

Below is the classic example for which the Likov‘s Substitution Principle is violated. In the example 2 classes are used: Rectangle and Square. Let‘s assume that the Rectangle object is used somewhere in the application. We extend the application and add the Square class. The square class is returned by a factory pattern, based on some conditions and we don‘t know the exact what type of object will be returned. But we know it‘s a Rectangle. We get the rectangle object, set the width to 5 and height to 10 and get the area. For a rectangle with width 5 and height 10 the area should be 50. Instead the result will be 100

下面是一个违反里氏代换原则的很典型的例子。例子中使用了2个类:Rectangle和Square。我们假设Rectangle对象在引用中的某个地方使用。我们扩展引用,添加Square类。square类使用工厂模式返回,在某些条件下,我们不能明确的指定哪种类型会返回。但是我们知道,他是Rectangle。我们得到了rectangle对象,设置宽度为5,高度为10,得到了一个区域。对于矩形来说宽度5高度10面积应该是50,而对于正方形来说结果是100。

 1 // Violation of Likov‘s Substitution Principle
 2 class Rectangle
 3 {
 4     protected int m_width;
 5     protected int m_height;
 6
 7     public void setWidth(int width){
 8         m_width = width;
 9     }
10
11     public void setHeight(int height){
12         m_height = height;
13     }
14
15
16     public int getWidth(){
17         return m_width;
18     }
19
20     public int getHeight(){
21         return m_height;
22     }
23
24     public int getArea(){
25         return m_width * m_height;
26     }
27 }
28
29 class Square extends Rectangle
30 {
31     public void setWidth(int width){
32         m_width = width;
33         m_height = width;
34     }
35
36     public void setHeight(int height){
37         m_width = height;
38         m_height = height;
39     }
40
41 }
42
43 class LspTest
44 {
45     private static Rectangle getNewRectangle()
46     {
47         // it can be an object returned by some factory ...
48         return new Square();
49     }
50
51     public static void main (String args[])
52     {
53         Rectangle r = LspTest.getNewRectangle();
54
55         r.setWidth(5);
56         r.setHeight(10);
57         // user knows that r it‘s a rectangle.
58         // It assumes that he‘s able to set the width and height as for the base class
59
60         System.out.println(r.getArea());
61         // now he‘s surprised to see that the area is 100 instead of 50.
62     }
63 }

Conclusion

结论

This principle is just an extension of the Open Close Principle and it means that we must make sure that new derived classes are extending the base classes without changing their behavior.

本原则只是开放封闭原则的一个扩展,它意味着我们应该确保新派生的类应该在不改变其基类行为的基础之上进行扩展。

原文地址:https://www.oodesign.com/liskov-s-substitution-principle.html

设计模式 之 里氏代换原则 (Liskov's Substitution Principle)

原文地址:https://www.cnblogs.com/wanpengcoder/p/12683348.html

时间: 2024-11-05 02:41:09

设计模式 之 里氏代换原则 (Liskov's Substitution Principle)的相关文章

设计模式之里氏代换原则(LSP)

里氏代换原则(Liskov Substitution Principle, LSP) 1 什么是里氏代换原则 里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的Liskov女士,在1987年的OOPSLA大会上发表的一篇文章<Data Abstraction and Hierarchy>里面提出来的,主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中的蕴涵的原理.2002年,我们前面单一职责原则中提到的软件工程大师Robert C. Martin,

设计模式SOLID - 里氏代换原则

Principles Rule!It's been a while since OOP/Design Pattern principles have been a topic on this blog, and now is as good time as any. The 1987 OOPSLA keynote address by Barbara Liskov contained what has become known as the Liskov Substitution Princip

里氏替换原则 Liskov Substitution Principle

里氏替换原则的介绍: 1) 里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院的以为姓里的女士提出的.2) 如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型.换句话说,所有引用基类的地方必须能透明地使用其子类的对象.3) 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法4) 里氏替换原则告诉我们,继承实际上让

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

设计模式中的里氏代换原则 Table of Contents 1 里氏代换原则 2 模式中的里氏代换原则 2.1 策略模代 2.2 合成模式 2.3 代理模式 3 如何继承 3.1 不要从具体类继承 3.2 避免错误继承 1 里氏代换原则 从开-闭原则中可以看出来面向对象的重要原则是创建抽象化,并从抽象化导出具体化.具 体化可以给出不同的版本,每一版本都给出不同的实现.里氏代换原则从另一个侧面描述 抽象化和具体化,里氏代换原则表明:一个软件如果使用的是一个基类的话,那么一定适 用于其子类,而且它

西游记之设计模式原则——里氏代换原则

里氏代换原则 --子类能替换父类 1 package lishidaihuan; 2 3 class TangSeng { 4 public void QuJing() { 5 System.out.println("施主,贫僧自东土大唐而来,去往西天拜佛求经!"); 6 } 7 } 8 9 class TuDi extends TangSeng { 10 public void QuJing() { 11 super.QuJing(); 12 System.out.println(&

前端用到的设计模式之开闭原则. 里氏代换原则

开闭原则,如果jQuery源码稍微了解,肯定知道它的应用了. 一个模块----函数或对象,应该凭着经验来判断, 对扩展开放,对修改关闭.------ 一般用继承实现扩展,用闭包来实现关闭. 为什么开闭原则?它跟复杂度有什么关系,? 复杂度,就是一个函数里包含的功能个数;当开闭原则不遵守时,想扩展功能,必然去原来的函数里添加代码,导致原来的函数功能增加. 里氏代换原则:是对开闭原则的补充,子类可以扩展父类,但不可改变父类. function changFangxing(height,width){

设计原则之里氏代换原则

设计原则之里氏代换原则 substitute  = replace 替换 sub 下 st石头 i我  tu土 te特别 我用石头替换下土,造了特比坚固的房子 hierarchy  ['harɑk] = level 等级 hi海豹  er儿子  ar are是  ch成龙 海豹儿子的雷霆战机等级是比成龙高 derive [di'raiv]  起源,派生 de德国  rive river河 德国的莱茵河起源于阿尔卑斯山 动机:         当我们创建类的层级(继承),我们继承一些类,创建一些派

里氏代换原则

若对于每一个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写的程序P中,用o1替换o2后,程序P的行为功能不变,则S是T的子类型. What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined

Java 设计模式(十一) 里氏替换原则(LSP)

里氏替换原则(Liskov Substitution Principle) LSP的基本概念 定义: 所有引用基类的地方必须能透明地使用其子类的对象 只要父类能出现的地方子类就可出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类(封装造成的多态性) 规范 子类必须完全实现父类的方法 在类中调用其他类时必然要使用父类或者接口,如果子类中不支持父类中的方法,自然就违背了LSP 子类要有自己的特性 子类是在父类的基础上实现的,有自己的特性 这也就导致了LSP的单向性