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&amp;MYSQL服务器配置说明
Oct 09 PHP
php插入中文到sqlserver 2008里出现乱码的解决办法分享
Jul 19 PHP
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
Jan 11 PHP
基于php常用函数总结(数组,字符串,时间,文件操作)
Jun 27 PHP
Drupal7中常用的数据库操作实例
Mar 02 PHP
小谈php正则提取图片地址
Mar 27 PHP
PHP大批量插入数据库的3种方法和速度对比
Jul 08 PHP
异步加载技术实现当滚动条到最底部的瀑布流效果
Sep 16 PHP
php中base64_decode与base64_encode加密解密函数实例
Nov 24 PHP
php启用sphinx全文搜索的实现方法
Dec 24 PHP
PHP面向对象类型约束用法分析
Jun 12 PHP
laravel框架中间件简单使用方法示例
Jan 25 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
一步一步学习PHP(6) 面向对象
2010/02/16 PHP
php数据库连接时容易出错的特殊符号问题
2010/09/01 PHP
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
2014/11/19 PHP
基于php判断客户端类型
2016/10/14 PHP
laravel中Redis队列监听中断的分析
2020/09/14 PHP
经典的解除许多网站无法复制文字的绝招
2006/12/31 Javascript
JavaScript获取/更改文本框的值的实例代码
2013/08/02 Javascript
javaScript 动态访问JSon元素示例代码
2013/08/30 Javascript
使用javascript实现页面定时跳转总结篇
2013/09/21 Javascript
JS复制内容到剪切板的实例代码(兼容IE与火狐)
2013/11/19 Javascript
JS实现IE状态栏文字缩放效果代码
2015/10/24 Javascript
深入浅析同源策略和跨域访问
2015/11/26 Javascript
ionic隐藏tabs的方法
2016/08/29 Javascript
js实现无缝滚动图(可控制当前滚动的方向)
2017/02/22 Javascript
微信小程序 数据绑定及运算的简单实例
2017/09/20 Javascript
Node.js+ELK日志规范的实现
2019/05/23 Javascript
教你搭建按需加载的Vue组件库(小结)
2019/07/29 Javascript
axios实现简单文件上传功能
2019/09/25 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
JS实现斐波那契数列的五种方式(小结)
2020/09/09 Javascript
Python实现的矩阵转置与矩阵相乘运算示例
2019/03/26 Python
Django ModelForm组件原理及用法详解
2020/10/12 Python
Python暴力破解Mysql数据的示例
2020/11/09 Python
Kenneth Cole官网:纽约时尚优雅品牌
2016/11/14 全球购物
集团薪酬管理制度
2014/01/13 职场文书
高中体育教学反思
2014/01/24 职场文书
监察建议书范文
2014/03/12 职场文书
开服装店计划书
2014/08/15 职场文书
2016新年慰问信范文
2015/03/25 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
员工手册编写范本
2015/05/14 职场文书
2019经典广告词集锦!
2019/07/02 职场文书
Nginx开源可视化配置工具NginxConfig使用教程
2022/06/21 Servers
win server2012 r2服务器共享文件夹如何设置
2022/06/21 Servers
Python可视化神器pyecharts绘制水球图
2022/07/07 Python
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
2022/09/23 MySQL