在面向对象的程序设计中。里氏替换原则(Liskov Substitution principle)是对子类型的特别定义。它由芭芭拉·利斯科夫(Barbara Liskov)在1987年在一次会议上名为“数据的抽象与层次”的演说中首先提出。

里氏替换原则的内容能够描写叙述为: “派生类(子类)对象能够替换其基类(超类)对象被使用。” 以上内容并不是利斯科夫的原文,而是译自罗伯特·马丁(Robert Martin)对原文的解读。

其原文为:

Let be a property provable about objects of type. Then should be true for objects of type where is a subtype of.

芭芭拉·利斯科夫与周以真(Jeannette Wing)在1994年发表论文并提出的以上的Liskov代换原则。----维基百科

里氏替换原则我个人的理解是:在继承关系中,父类的对象假设替换为子类的对象,他原来运行的行为依旧保持不变,那么这种程序才符合里氏替换原则,否则违背了里氏替换原则。

以下我们看这样一个实例,体会下,里氏替换原则是在什么情况下违背的。

一个简单的继承结构,在子类中,重写父类的方法calc方法。

父类Calc:

package cn.design.pattern2016032004LiskovSubstitutionPrinciple;

public class Calc {

	public void calc(int a, int b) {
// a-b = ?
System.out.println(a + " - " + b + " = " + (a - b)); }
}

子类CalcSon,通过将父类中calc这种方法重写为两个数相加。

package cn.design.pattern2016032004LiskovSubstitutionPrinciple;

public class CalcSon extends Calc{

	public void calc(int a, int b) {
// a+b = ?
System.out.println(a + " + " + b + " = " + (a + b));
} // other method
public void addThem(int a, int b) {
System.out.println(a + b);
}
}

測试类:这里假设符合里氏替换原则的话,那么应该说将父类的调用的这个地方直接换为子类的话,那么原来的行为不会发生不论什么的改变。

可是以下的程序证明了,这种做法是违背了里氏替换原则的。将原先父类调用的替换为子类的时候。会由原来的父类的方法:减法。变为如今子类中的:加法。结果发生变化,从而违背了里氏替换原则。

Calc cal = new Calc();
cal.calc(10, 20); /**
* 依据里氏替换原则。当父类替换为子类的时候,使用父类的时候的行为不应该
* 发生变化,那么以下的这段代码,显然发生了变化,这样显然违反了里氏替换
* 原则。
*/
Calc calcSon = new CalcSon();
calcSon.calc(10, 20);

我们在子类继承父类之后,重写了父类的方法时,须要注意,这种做法并不好,减少了整个继承体系的复用性。出错几率会对应的添加。

总结前人的诸多经验来看,里氏替换原则主要是有四点:

1. 子类不要覆盖父类的非抽象的方法。

能够实现其抽象方法。

2. 子类能够实现自己独有的方法。

3. 子类的方法重写父类方法的时候。參数部分,要比父类的參数范围要大或者等于(宽松)。释义:举个样例>假设说父类的方法中形參是ArrayList,那么,其子类重写这种方法的时候,形參要是List.

4. 子类重写父类方法的时候,返回值要求。父类的返回值要比子类的返回值要小于或者等于。

面对这种情况,一般的,将当前的继承结构解除掉。变为依赖或者聚合组合的形式。

抽象出更高一层的抽象类,定义好这种一个抽象方法。同一时候由原先的两个类继承实现。

public abstract class Calculator {

	public abstract void calc(int a, int b);
}
public class Calc extends Calculator{

	public void calc(int a, int b) {
// a-b = ?
System.out.println(a + " - " + b + " = " + (a - b)); }
}

public class CalcSon extends Calculator{

	public void calc(int a, int b) {
// a+b = ?
System.out.println(a + " + " + b + " = " + (a + b));
} // other method
public void addThem(int a, int b) {
System.out.println(a + b);
}
}


通过这种途径将原来的继承结构又一次解构重组后的继承体系,应该说相对来说。出错的几率大大减少了。

源代码已经上传至GitHub:下载设计模式代码


"围观"设计模式(2)--里氏替换原则(LSP,Liskov Substitution Principle)的更多相关文章

  1. 北风设计模式课程---里氏替换原则(Liskov Substitution Principle)

    北风设计模式课程---里氏替换原则(Liskov Substitution Principle) 一.总结 一句话总结: 当衍生类能够完全替代它们的基类时:(Liskov Substitution P ...

  2. IOS设计模式的六大设计原则之里氏替换原则(LSP,Liskov Substitution Principle)

    定义 里氏替换原则的定义有两种,据说是由麻省理工的一位姓里的女士所提出,因此以其名进行命名. 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换 ...

  3. 里氏替换原则(Liskov Substitution Principle)

    开放封闭原则(Open Closed Principle)是构建可维护性和可重用性代码的基础.它强调设计良好的代码可以不通过修改而扩展,新的功能通过添加新的代码来实现,而不需要更改已有的可工作的代码. ...

  4. 里氏替换原则(Liskov Substitution Principle) LSP

    using System; using System.Collections.Generic; using System.Text; namespace LiskovSubstitutionPrinc ...

  5. 面向对象设计原则 里氏替换原则(Liskov Substitution Principle)

    里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一. 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现. LSP是继承复用的基石,只 ...

  6. 【设计模式六大原则2】里氏替换原则(Liskov Substitution Principle)

      肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑.其实原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的. 定义1:如果对 ...

  7. 设计模式六大原则(2):里氏替换原则(Liskov Substitution Principle)

    肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑.事实上原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的. 定义1:假设对每 ...

  8. 2.里氏替换原则(Liskov Substitution Principle)

    1.定义 里氏替换原则的定义有两种,据说是由麻省理工的一位姓里的女士所提出,因此以其名进行命名. 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都 ...

  9. 面象对象设计原则之三:里氏替换原则(The Liskov Substitution Principle,LSP)

    里氏代换原则由2008年图灵奖得主.美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出.其严格表述如下:如果对每一个类型为S的 ...

随机推荐

  1. Win7下安装pip

    1.首先下载setuptools,下载地址https://pypi.python.org/pypi/setuptools#downloads2.解压下载后的文件,进入命令行,将目录切换到解压后文件夹所 ...

  2. LaTeX如何设置段落层次结构

    Latex的文档层次结构大约有5层,分别是: section — subsection — subsubsection — paragraph — subparagraph 具体使用可以参考下面的例子 ...

  3. api的mock开源工具;api文档生成器;api的mock工具;阿里系;其他开源

    django-rest-framework,即drf的api文档,包括自带的文档和其他三方文档,比如swagger.DRF Docs等 https://www.django-rest-framewor ...

  4. Qt 维护工具MaintenanceTool.exe 使用

    QT如何管理组件(解决“要继续此操作,至少需要一个有效且已启用的储存库”问题) 转载2017-10-26 01:48:46 标签:qt QT的组件管理软件并没有在开始菜单或者桌面添加快捷方式(5.9版 ...

  5. mysql创建、删除用户与授权(linux測试)

    注:我的执行环境是SUSE Linux + mysql5.6 一.创建用户:  命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password';  ...

  6. eclipse 添加 Courier New 字体

    下载了eclipse3.7,发现这个版本默认的字体不是Courier New,后来通过eclipse->windows->preferences->general->apper ...

  7. jdk1.7下载路径

    http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

  8. 使用apache-cxf-2.2.10来制作一个极简版WebService程序

    原想拿最新版cxf来制作的,无奈Apache的zip包总下不下来,国内的apache-cxf-2.2.10却一蹴而就,也就用了这个版本.下载地址是:http://pan.baidu.com/s/1td ...

  9. 【转】TextView的详细属性

    1.简介: TextView控件可用来展示文本信息(包括HTML文本),可以手动来设置可编辑或不可编辑. 2.创建对象: 1)在代码中通过new的方式创建,创建,设置文本,样式后,通过setConte ...

  10. [笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger

    [笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchan ...