在面向对象的程序设计中。里氏替换原则(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. TCP常用网络和木马使用端口对照表,常用和不常用端口一览表

    [开始-运行- CMD , 输入 netstat -an 然后回车就可以查看端口] 端口: 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“”是无效端口,当你试 ...

  2. jquery之超简单的div显示和隐藏特效demo

    闲着无聊,看到某视频网站上讲的DIV显示和隐藏的效果,自己也写了一个. 觉得还是挺简单的. 前端改变世界!嘿嘿,还挺有成就感 <!DOCTYPE html PUBLIC "-//W3C ...

  3. Javascript屏蔽鼠标右键-超简单,不过还是记录一下

    Javascript屏蔽鼠标右键,其实作用也不大,也许是为了防止别人查看源代码,其实想查看源代码有多种途径,未必需要通过鼠标右键.不过当我们自定义鼠标右键弹出菜单时,也许需要这些. 下面是源码: 1 ...

  4. JSP学习笔记(四):文件上传

    JSP 可以与 HTML form 标签一起使用,来允许用户上传文件到服务器.上传的文件可以是文本文件或图像文件或任何文档.我们使用 Servlet 来处理文件上传,使用到的文件有: upload.j ...

  5. hybrid app开发中用到的html5新特性localStorage、sessionStorage和websql database

    近期在项目中进行hybrid app开发,项目中有大量的js代码执行在android设备上. 使用到了非常多HTML5的新特性,之前没有遇到过,不了解.这里记录下添加点前端的知识.混合式app开发中. ...

  6. 后缀树(Suffix Trie)子串匹配结构

    Suffix Trie 又称后缀Trie或后缀树.它与Trie树的最大不同在于,后缀Trie的字符串集合是由指定字符串的后缀子串构成的.比如.完整字符串"minimize"的后缀子 ...

  7. Discuz常见小问题-如何删除用户

    用户-用户管理,直接拉到底部点搜索   切换到最后一页,然后勾选要删除的用户(最后一页就是最新注册的用户)   要勾选两个选项,删除过程比较长,不要中途退出,等待删除完毕   再次搜索用户就少一个了

  8. 退出app 退出应用程序

    退出app的两种方式1   创建activity的基类,让所有的activity都继承该基类,在基类中创建一个静态的activity列表,并在oncreate方法添加该activity,在退出时,遍历 ...

  9. java中形参个数可变的方法使用

    public class Varargs { public static void main(String[] args) { test(3,"java","C++&qu ...

  10. ajax交互Struts2的action(1)

    1.客户端网页代码 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://w ...