在面向对象的程序设计中。里氏替换原则(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. 自定义控件 淘宝头条【ViewFlipper】

    简易版 代码 ); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Acti ...

  2. Java实现图片的裁剪

    需求: 有一张位置大小的图片,现在需要根据这张原图得到指定尺寸的图片,且得到的图片要符合原先图片的比例,就是在原图的基础上等比例缩放得到图片后,在进行剪裁,这样保证得到的图片是原图的一部分,而不是将原 ...

  3. 【itercast OSI 七层网络模型 学习笔记】Layer 1 物理层

    NIC:网卡(基本上是一层功能) 传输介质:以太网,分有线和无线 开始以太网只有10Mbps的吞吐量,使用的是带有冲突检测的载波侦听多路访问(CSMA/CD,Carrier Sense Multipl ...

  4. struts2-core-2.0.14更新到2.3.15

    struts2-core-2.0.14更新到2.3.15 将低版本的struts2-core更新到最新版本2.3.15,更新jar包,有这个几个 1. struts2-core-2.0.14.jar ...

  5. SQL语法 之 操作语句

    一.插入语句 1.插入单行记录 INSERT INTO table_name|view_name[(column1_name [,column2_name, ... ])] VALUES( value ...

  6. Eclipse自动编译NDK/JNI的三种方法

    一.Eclipse关联cygwin 1. 工程->右击选择Properties->选择Builders,在Builders中选择New创建一个Program 2. 参数配置 二.Eclip ...

  7. java 泛型--桥方法

    因为 java 在编译源码时, 会进行 类型擦除, 导致泛型类型被替换限定类型(无限定类型就使用 Object). 因此为保持继承和重载的多态特性, 编译器会生成 桥方法. 本文最后附录所有源码. P ...

  8. windows合并文件夹窗口

      windows合并文件夹窗口 CreateTime--2017年7月26日16:28:14Author:Marydon 右击任务栏-->属性-->任务栏按钮选项-->选择“始终合 ...

  9. Apache 整合 Acitve Directory 達成 one single signon

    原文地址:http://blog.hsdn.net/1266.html 我的公司使用AD進行使用者驗證,因此在使用者操作的便利性考量前提下.如何讓使用者不需要重覆輸入帳號與密碼,而直接抓取使用者已經登 ...

  10. C3P0连接参数解释

    <c3p0-config> <default-config> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数.Default: 3 --> < ...