替换原则由MIT计算机科学实验室的Liskov女士在1987年的OOPSLA大会上的一篇文章中提出,主要阐述有关继承的一些原则,故称里氏替换原则。

2002年,Robert C.Martin出版了一本名为《Agile Software Development Principles Patterns and Practices》的书,在书中他把里氏替换原则最终简化成一句话:“Subtypes must be substitutable for their base types”(子类必须能够替换成它们的基类。)
 
1.LSP的内容
里氏替换原则(Liskov Substitution Principle, LSP)的定义和主要思想如下:由于面向对象编程技术中的继承在具体的编程中过于简单,在许多系统的设计和编程实现中,我们并没有认真地、理性地思考应用系统中各个类之间的继承关系是否合适,派生类是否能正确地对其基类中的某些方法进行重写等问题。因此经常出现滥用继承或者错误地进行了继承等现象,给系统的后期维护带来了不少麻烦。这就需要我们有一个设计原则来遵循,它就是替换原则。
LSP指出:子类类型必须能够替换掉它们的父类型、并出现在父类能够出现的任何地方。它指导我们如何正确地进行继承和派生,并合理地重用代码。此原则认为,一个软件实体如果使用一个基类的话,那么一定适用于其子类,而且这根本不能察觉出基类对象和子类对象的区别。想一想,是不是和多态的概念比较像?
2.LSP主要是针对继承的设计原则
因为继承与派生是OOP的一个主要特性,能够减少代码的重复编程实现,从而实现系统中的代码复用,但是如何正确地进行继承设计和合理地应用继承机制呢?
这就是LSP所要解决的问题:
如何正确地进行继承方面的设计?
最佳的继承层次如何获得?
怎么样避免所设计的类层次陷入不符合OCP原则的状况?
那如何遵守该设计原则呢?
1)父类的方法都要在子类中实现或者重写,并且派生类只实现其抽象类中声明的方法,而不应当给出多余的方法定义或实现
2)在客户端程序中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期绑定(动态多态)。
如果A、B两个类违反了LSP的设计,通常的做法是创建一个新的抽象类C,作为两个具体类的超类,奖A和B的共同行为移动到C中,从而解决A和B的行为不完全一致的问题。
不过PHP对LSP的支持并不好,缺乏向上转型等概念,只能通过一些曲折的方法实现。对于这个原则,这里就不细讲了。
 
下面给出一个缓存的实现接口,用抽象类做基类,遵循LSP实现其设计。

<?php
abstract class Cache
{
/**
* 设置一个缓存变量
* @param $key 缓存key
* @param $value 缓存内容
* @param int $expire 缓存时间(秒)
* @return boolean 是否缓存成功
*/
public abstract function set($key, $value, $expire = 60); /**
* 获取一个已经缓存的
* @param $key 缓存key
* @return mixed 缓存内容
*/
public abstract function get($key); /**
* 删除一个已经缓存的变量
* @param $key 缓存key
* @return boolean 是否删除成功
*/
public abstract function del($key); /**
* 删除全部缓存变量
* @return boolean 是否删除成功
*/
public abstract function delAll(); /**
* 检测是否存在对应的缓存
* @param $key 缓存key
* @return boolean 是否存在
*/
public abstract function has($key);
}
如果现在要求实现文件、memcache、accelerator等各种机制下的缓存,只需要继承这个抽象类并实现其抽象方法即可。
LSP中代码的不仅仅是功能,还名手语意。试思考:白马可以代换马,而牛同样作为劳动力,可代换马否?高跟鞋也是鞋子,男人穿高跟鞋又是否能接受?

里氏替换原则(LSP)的更多相关文章

  1. .net学习之继承、里氏替换原则LSP、虚方法、多态、抽象类、Equals方法、接口、装箱拆箱、字符串

    1.继承(1)创建子类对象的时候,在子类对象中会为子类对象的字段开辟空间,也会为父类的所有字段开辟空间,只不过父类私有的成员访问不到(2)子类从父类继承父类所有的非私有成员,但是父类的所有字段也会创建 ...

  2. 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...

  3. 里氏替换原则LSP(继承规范)

    继承的优点: 1.代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性. 2.提高代码的重用性. 3.子类可以形似父类,但又异于父类. 4.提高代码的可扩展性,实现父类的方法就可以“为所欲为” ...

  4. 架构师之路——里氏替换原则LSP

    定义: 如果对每一个对类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型. 内容: 里氏替换原则通 ...

  5. &quot;围观&quot;设计模式(2)--里氏替换原则(LSP,Liskov Substitution Principle)

    在面向对象的程序设计中.里氏替换原则(Liskov Substitution principle)是对子类型的特别定义.它由芭芭拉·利斯科夫(Barbara Liskov)在1987年在一次会议上名为 ...

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

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

  7. 六大设计原则(二)LSP里氏替换原则

    里氏替换原则LSP(Liskov Subsituation Principle) 里氏替换原则定义 所有父类出现的地方可以使用子类替换并不会出现错误或异常,但是反之子类出现的地方不一定能用父类替换. ...

  8. oc之里氏替换原则

    1. 里氏替换原则. LSP 子类对象可以替换父类对象的位置,并且程序的功能不受影响. 为什么? 1). 指针是1个父类类型,但是我们确给了指针1个子类对象的地址. 这样做当然是可以的,因为你要1个父 ...

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

    里氏替换原则(LSP)由来: 最早是在 妖久八八 年, 由麻神理工学院得一个女士所提出来的. 定义: 1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 ...

随机推荐

  1. (PMP)解题技巧和典型题目分析(每日20题)

    3.11 1.A(C),2.D,3.A,4.B,5.A(C),6.D(A),7.D,8.A(D),9.B,10.D(B), 11.C(B),12.C(D),13.B,14.D,15.C,16.C(D) ...

  2. 理解存储引擎MyISAM与InnoDB

    1.MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.不 ...

  3. 对python3中pathlib库的Path类的使用详解

    原文连接   https://www.jb51.net/article/148789.htm 1.调用库 ? 1 from pathlib import 2.创建Path对象 ? 1 2 3 4 5 ...

  4. 为什么重写equals一定要重写hashCode?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解. ...

  5. C# 服务开发

    1. 执行权限 对于一般服务项目,需要使用管理员权限打开Visual Studio.右击项目 -> 属性 -> 安全性,如下图: 勾选红框中部分,项目中会增加文件 app.mainfest ...

  6. HTTP 初步探究

    网络上存在很多资源,也持续不断地生成新的资源.为了新建.获取和操作这些资源,引来了两个问题:如何定位资源,如何对他们进行操作.第一个问题引申出了 URI / URL 即 uniform resourc ...

  7. Servlet创建完美教程

    简介:Servlet其实是Server Let的缩写,是服务器端应用程序.  java中有一个applet是客户端应用程序,与servlet对应.applet已经过时.Servlet作用:能在B/S架 ...

  8. msfconlose基本命令

    命令 简介 back 从当前上下文 banner 显示显示一个令人敬畏的metasploit横幅 cd 更改当前工作目录 color 切换颜色 connect 与主机通信 edit 使用$ VISUA ...

  9. GC算法基础

    寻找垃圾对象的算法:1. 引用计数(无法处理循环引用) 2. 根寻法(被广泛引用在gc算法中) 清理垃圾的算法: 1. 标记复制  2. 标记清理  3. 标记整理 分代算法的好处: 1. 分代处理, ...

  10. build.gradle

    1.将Eclipse项目导入到Android studio 中 很多点9图出现问题解决方法: 在build.gradle里添加以下两句: aaptOptions.cruncherEnabled = f ...