在面向对象的程序设计中。里氏替换原则(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. [Linux] ubuntu server sudo出现sudo:must be setuid root 完美解决办法

    1.开机按shift或esc先进行recovery模式 2.选择root命令行模式 3.先执行 #mount -o remount,rw / 这个很重要,网上找的很多资料都不全没有这步造成无法恢复成功 ...

  2. 显示所有环境变量:env 或者 printenv

    显示所有环境变量:env 或者 printenv

  3. LaTeX图片环境 Picture environment

    Picture environment If you need to include simple diagrams or figures in your document, the picture  ...

  4. Git 学习(二)版本库创建

    Git 版本库创建 什么是版本库(repository)? 可理解为文件仓库.由Git管理每个文件的新增.修改及删除,但这个仓库可以追溯历史.可还原至任意历史节点. 版本库创建 创建一个版本库非常简单 ...

  5. Git分布式开发之生成ssh公钥

    1.在Preferences>Network Connections>SSH2,切换至Key Management面板,点击 2.点击生成Genarate RSA Key,并修Commne ...

  6. 数学图形(2.8)Viviani曲线

    维维亚尼(Viviani , Vincenzo)意大利数学家.1622年4月5日生于托斯卡纳大区佛罗伦萨:1703年9月22日卒于佛罗伦萨. 这是一个圆柱与一个球相交而生成的曲线. #http://w ...

  7. 完整的ASP.NET存储过程分页,排序,鼠标移至变色

    首先建立一个存储过程如下(MySQL数据库):CREATE DEFINER=`root`@`localhost` PROCEDURE `pagination`(       in tbName var ...

  8. Django安装和配置环境变量

    一.windows系统安装Django 1.先安装python2.x or 3.x软件.(记得勾选pip3和添加python自己的环境变量) 下载地址:http://www.python.org/ 2 ...

  9. jsp+servlet+jdbc实现对数据库的增删改查

    一.JSP和Servlet的简单介绍: 1.Servlet和JSP简介: Java开发Web应用程序时用到的技术主要有两种,即Servlet和JSP,Servlet是在服务器端执行的Java程序,一个 ...

  10. flex 无法将“<mx:>”解析为组件执行.解决方法

    转自:http://www.myexception.cn/flex/434924.html 问题描述: flex项目导入早期版本 无法将“<mx:******>”解析为组件执行. 如图: ...