LSP是唯一一个以人名命名的设计原则,并且作者还是一个“女博士” 

=============================================================


LSP,Liskov substitution principle,中文翻译为“里氏替换原则”。

这是面向对象原则中唯一一个以人名命名的原则,尽管Liskov在中国的知名度没有UNIX的几位巨匠(Kenneth Thompson、Dennis Ritchie)、GOF四人帮那么响亮,但查一下资料,你会发现事实上Liskov也是非常牛的:2008年图灵奖获得者,历史上第一个女性计算机博士学位获得者。其具体资料能够在维基百科上查阅:http://en.wikipedia.org/wiki/Barbara_Liskov

言归正传,我们来看看LSP原则究竟是怎么一回事。

LSP最原始的解释当然来源于Liskov女士了,她在1987年的OOPSLA大会上提出了LSP原则,1988年,她将文章发表在ACM的SIGPLAN Notices杂志上,当中详解了LSP原则:

A type hierarchy is composed of subtypes and supertypes. The intuitive idea of a subtype is one whose objects provide all the behavior of objects of another type (the supertype) plus something extra.What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

英文比較长,看起来比較累,我们简单的翻译并归纳一下:

1) 子类的对象提供了父类的全部行为,且加上子类额外的一些东西(能够是功能,也能够是属性);

2) 当程序基于父类实现时,假设将子类替换父类而程序不须要改动,则说明符合LSP原则

尽管我们略微翻译和整理了一下,但实际上还是非常拗口和难以理解。

幸好还有Martin大师也认为这个不怎么通俗易懂,Robert Martin在1996年为《C++ Reporter》写了一篇题为《The The Liskov Substitution Principle》的文章,解释例如以下:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

翻译一下就是:函数使用指向父类的指针或者引用时,必须能够在不知道子类类型的情况下使用子类的对象。

Martin大师解释了一下,相对easy理解多了。但Martin大师还不满足,在2002年,Martin在他出版的《Agile   Software   Development   Principles   Patterns   and   Practices》一书中,又进一步简化为:

Subtypes   must   be   substitutable   for   their   base   types。

翻译一下就是:子类必须能替换成它们的父类。

经过Martin大师的两次翻译,我相信LSP原则本身已经解释得比較easy理解了,但问题的关键是:怎样满足LSP原则?或者更通俗的讲:什么情况下子类才干替换父类?

我们知道,对于调用者来说(Liskov解释中提到的P),和父类交互无非就是两部分:调用父类的方法、得到父类方法的输出,中间的处理过程,P是无法知道的。

也就是说,调用者和父类之间的联系体如今双方面:函数输入,函数输出。具体例如以下图:

有了这个图之后,怎样做到LSP原则就清晰了:

1) 子类必须实现或者继承父类全部的公有函数,否则调用者调用了一个父类中有的函数,而子类中没有,执行时就会出错;

2) 子类每一个函数的输入參数必须和父类一样,否则调用父类的代码不能调用子类;

3) 子类每一个函数的输出(返回值、改动全局变量、插入数据库、发送网络数据等)必须不比父类少,否则基于父类的输出做的处理就没法完毕。

有了这三条原则后,就能够非常方便的推断类设计是否符合LSP原则了。须要注意的是第3条的关键是“不比父类少”,也就是说能够比父类多,即:父类的输出是子类输出的子集。

有的朋友看到这三条原则可能有点纳闷:这三条原则一出,那子类还有什么差别哦,岂不都是一样的实现了,那还会有不同的子类么?

事实上假设细致研究这三条原则,就会发现当中仅仅是约定了输入输出,而并没有约束中间的处理过程。比如:相同一个写数据库的输出,A类能够是读取XML数据然后写入数据库,B类能够是从其他数据库读取数据然后本地的数据库,C类能够是通过分析业务日志得到数据然后写入数据库。这3个类的处理过程都不一样,但最后都写入数据到数据库了。

LSP原则最经典的样例就是“长方形和正方形”这个样例。从数学的角度来看,正方形是一种特殊的长方形,但从面向对象的角度来观察,正方形并不能作为长方形的一个子类。原因在于对于长方形来说,设定了宽高后,面积 = 宽 * 高;但对于正方形来说,设定高同一时候就设定了宽,设定宽就同一时候设定了高,最后的面积并非等于我们设定的 宽 * 高,而是等于最后一次设定的宽或者高的平方。

具体代码样比例如以下:

Rectangle.java

package com.oo.java.principles.lsp;/*** 长方形*/
public class Rectangle {protected int _width;protected int _height;/*** 设定宽* @param width*/public void setWidth(int width){this._width = width;}/*** 设定高* @param height*/public void setHeight(int height){this._height = height;}/*** 获取面积* @return*/public int getArea(){return this._width * this._height;}
}

Square.java

package com.oo.java.principles.lsp;/*** 正方形*/
public class Square extends Rectangle {/*** 设定“宽”,与长方形不同的是:设定了正方形的宽,同一时候就设定了正方形的高*/public void setWidth(int width){this._width = width;this._height = width;}/*** 设定“高”,与长方形不同的是:设定了正方形的高,同一时候就设定了正方形的宽*/public void setHeight(int height){this._width = height;this._height = height;}}

UnitTester.java

package com.oo.java.principles.lsp;public class UnitTester {public static void main(String[] args){Rectangle rectangle = new Rectangle();rectangle.setWidth(4);rectangle.setHeight(5);//例如以下assert推断为trueassert( rectangle.getArea() == 20);rectangle = new Square();rectangle.setWidth(4);rectangle.setHeight(5);//例如以下assert推断为false,断言失败,抛出java.lang.AssertionErrorassert( rectangle.getArea() == 20);}
}

上面这个样例同一时候也给出了一个推断子类是否符合LSP的取巧的方法,即:针对父类的单元測试用例,传入子类是否也能够測试通过。假设測试能够通过,则说明符合LSP原则,否则就说明不符合LSP原则

转载于:https://www.cnblogs.com/mfrbuaa/p/3778484.html

连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则相关推荐

  1. 面向对象葵花宝典:思想、技巧与实践(36) - 设计原则如何用?

    经过前面深入的阐述,SOLID的原则我们已经基本上讲清楚了,但如果想熟练的应用SOLID原则,仅仅知道SOLID是什么(what)还不够,我们还需要知道SOLID原则在什么时候和什么场景应用(when ...

  2. 【Java设计模式 面向对象设计思想】一 再谈面向对象和封装、抽象、继承、多态四大特性

    回看最初的目标:[Java设计模式 学习目标及大纲]高质量代码的标准及实现路径在这篇Blog里我们明确了什么是高质量的代码:易维护.易读.易扩展.灵活.简洁.可复用.可测试,也知道高质量代码的达成路径 ...

  3. 猫和老鼠面向对象java语言_面向对象葵花宝典- 完整版.pdf

    构架,均衡,负载,网站,应用,net,存储系统,java,设计模式,互联网 面向对象葵花宝典 /yunhua_lee 面向对象葵花宝典 目录 第一部分:面向对象基础6 1.面向对象概述6 1.1. 程 ...

  4. 面向对象编程思想概览(一)类和对象

    一.简介 生活中有许多技巧值得我们在程序设计中模仿和借鉴.采用类的思想可以方便地把具有相同属性和方法归为一类,从而简化编程.本讲利用生活的常见示例,浅显通俗的语言,生动地介绍了面向对象编程中类与对象的 ...

  5. App 后台架构设计方案 设计思想与最佳实践

    CSDN 2016博客之星评选结果公布      [系列直播]零基础学习微信小程序!        "我的2016"主题征文活动     博客的神秘功能 App 后台架构设计方案 ...

  6. 编写程序描述影视歌三栖艺人。需求说明:请使用面向对象的思想,设计自定义类,描述影视歌三梄艺人。...

    编写程序描述影视歌三栖艺人.需求说明:请使用面向对象的思想,设计自定义类,描述影视歌三梄艺人. 实现思路: 1) 分析影视歌三栖艺人的特性:可以演电影,可以演电视剧,可以唱歌 2) 定义多个接口描述特 ...

  7. 面向对象编程思想 - 月亮晶石的日志 - 网易博客

    面向对象是一种新兴的程序设计方法,或者说它是一种新的程序设计范型,其基本思想是使用对象,类,继承,封装,消息等基本概念来进行程序设计.   它是从现实世界中客观存在的事物(即对象)出发来构造软件系统, ...

  8. 用面向对象的思想探讨游戏“魔兽争霸”(1)

    [文章标题]用面向对象的思想探讨游戏"魔兽争霸"(1) [文章作者]曾健生 [作者邮箱]zengjiansheng1@126.com [作者QQ]190678908 [作者博客]h ...

  9. 理解面向对象编程思想

    面向过程 面向过程概念:是一种编程思想,就是分析出解决问题所需要的步骤,然后用方法把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了. 通过下面造车案例了解 面向过程特点:开发周期慢,但是性能 ...

  10. Java学习——面向对象编程思想

    目录 一. 基本概念 二. 面向对象与面向过程的区别 三. 面向对象程序设计的类与对象 3.1 对象 3.2 类 四. 面向对象的四大特征 4.1 抽象 4.2 继承 4.3 封装 4.4 多态 1) ...

最新文章

  1. arduino char*转string_【201期】面试官:String长度有限制吗?是多少?还好我看过...
  2. SM30需要传输请求
  3. java最好的开发工具_IntelliJ IDEA Ultimate Edition 2018 最好的 Java 开发工具
  4. 虚拟机登陆别的服务器吗,云服务器只能用虚拟机登录吗
  5. 关于 TypeScript 联合类型 union type 赋值的一个错误消息
  6. Java web登录拦截器_SpringMVC拦截器(实现登录验证拦截器)
  7. ejb 示例 2018_Java EE EJB拦截器教程和示例
  8. 信息系html5论文,基于HTML5的智力游戏设计电子信息工程本科学生毕业论文.doc
  9. 实现环形和扇形百分比
  10. 【重磅分享】从零到一搭建推荐系统指南白皮书.pdf(附48页下载链接)
  11. Teamcenter 2007 之 Part 物件关联
  12. linux删除0字节的文件,如何在linux中删除许多0字节的文件?
  13. VScode Remote 直接打开远程服务器目录进行调试
  14. 关于高德地图坐标批量手动拾取的简易办法
  15. windows7 系统下载(2)
  16. python解析xml文件为pdf_用Python解析XML文件的软件实现
  17. 试图通俗地讲一下庞加莱猜想是怎么回事
  18. WebGIS开发快速入门
  19. Shave Beaver! CodeForces - 331B2 (线段树)
  20. Oracle怎么查hex值,oracle 进制转换 HEX/DECIMAL/OCTAL/BINARY

热门文章

  1. adb pull 报错处理:adb: error: cannot create file/directory 'E:\': No such file or directory
  2. Keras实现text classification文本二分类
  3. Tech-Ed2004的收获
  4. IOS 中description 和 debugDescription的区别
  5. 利用C++不使用递归,循环和goto,打印1到100 的某一答案分析
  6. Android适配之百分比的简单用法
  7. Java编程思想1-对象导论
  8. Oralce SQLPlus 以及shell脚本中spool输出到文件时的格式化输出
  9. 过滤器 拦截器 controller 页面 的执行顺序
  10. 图的更多相关算法-2(最小生成树)