PHP面向对象五大原则之里氏替换原则(LSP)详解


Posted in PHP onApril 08, 2018

本文实例讲述了PHP面向对象五大原则之里氏替换原则(LSP)。分享给大家供大家参考,具体如下:

替换原则由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中代码的不仅仅是功能,还名手语意。试思考:白马可以代换马,而牛同样作为劳动力,可代换马否?高跟鞋也是鞋子,男人穿高跟鞋又是否能接受?

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
将PHP作为Shell脚本语言使用
Oct 09 PHP
在Windows中安装Apache2和PHP4的权威指南
Oct 09 PHP
PHP中设置时区方法小结
Jun 03 PHP
PHP不用第三变量交换2个变量的值的解决方法
Jun 02 PHP
php输入数据统一类实例
Feb 23 PHP
JavaScript实现滚动栏效果的方法
Apr 27 PHP
服务器迁移php版本不同可能诱发的问题
Dec 22 PHP
Yii数据库缓存实例分析
Mar 29 PHP
Zend Framework入门教程之Zend_Registry组件用法详解
Dec 09 PHP
PHP 文件上传后端处理实用技巧方法
Jan 06 PHP
PHP调用API接口实现天气查询功能的示例
Sep 21 PHP
php使用redis的几种常见操作方式和用法示例
Feb 20 PHP
PHP实现微信红包金额拆分试玩的算法示例
Apr 07 #PHP
PHP面向对象五大原则之接口隔离原则(ISP)详解
Apr 04 #PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
Apr 04 #PHP
PHP面向对象五大原则之单一职责原则(SRP)详解
Apr 04 #PHP
PHP基于面向对象实现的留言本功能实例
Apr 04 #PHP
PHP设计模式之工厂模式定义与用法详解
Apr 03 #PHP
PHP设计模式之原型模式定义与用法详解
Apr 03 #PHP
You might like
咖啡的植物学知识
2021/03/03 咖啡文化
PHP实现文件下载断点续传详解
2014/10/15 PHP
yiic命令时提示“php.exe”不是内部或外部命令的解决方法
2014/12/18 PHP
PHP获取数组最后一个值的2种方法
2015/01/21 PHP
php中isset与empty函数的困惑与用法分析
2019/07/05 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
javascript中的有名函数和无名函数
2007/10/17 Javascript
getElementsByTagName vs selectNodes效率 及兼容的selectNodes实现
2010/02/26 Javascript
JavaScript学习笔记记录我的旅程
2012/05/23 Javascript
JSuggest自动匹配下拉框使用方法(示例代码)
2013/12/27 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
2014/05/08 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
2014/07/17 Javascript
js使用html()或text()方法获取设置p标签的显示的值
2014/08/01 Javascript
jquery任意位置浮动固定层插件用法实例
2015/05/29 Javascript
纯JavaScript代码实现移动设备绘图解锁
2015/10/16 Javascript
详谈Angular路由与Nodejs路由的区别
2017/03/05 NodeJs
利用Javascript裁剪图片并存储的简单实现
2017/03/13 Javascript
为输入框加入数字js校验代码分享
2017/11/02 Javascript
详解webpack+express多页站点开发
2017/12/22 Javascript
node作为中间服务层如何发送请求(发送请求的实现方法详解)
2018/01/02 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
2018/04/01 Javascript
基于Bootstrap下拉框插件bootstrap-select使用方法详解
2018/08/07 Javascript
微信小程序中上传图片并进行压缩的实现代码
2018/08/28 Javascript
vue+iview分页组件的封装
2020/11/17 Vue.js
[02:56]DOTA2英雄基础教程 巨魔战将
2013/12/10 DOTA
Python中with及contextlib的用法详解
2017/06/08 Python
python去除文件中重复的行实例
2018/06/29 Python
python实现画五角星和螺旋线的示例
2019/01/20 Python
Python shutil模块用法实例分析
2019/10/02 Python
python用quad、dblquad实现一维二维积分的实例详解
2019/11/20 Python
python3 tkinter实现添加图片和文本
2019/11/26 Python
python 读取数据库并绘图的实例
2019/12/03 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
2020/06/02 Python
Marlies Dekkers内衣法国官方网上商店:国际知名的荷兰内衣品牌
2019/03/18 全球购物
工会主席事迹材料
2014/06/03 职场文书
感恩母亲节活动总结
2015/02/10 职场文书