PHP面向对象五大原则之依赖倒置原则(DIP)详解


Posted in PHP onApril 08, 2018

本文实例讲述了PHP面向对象五大原则之依赖倒置原则(DIP)。分享给大家供大家参考,具体如下:

什么是依赖倒置呢?简单地讲就是将依赖关系倒置为依赖接口,具体概念如下:

1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象(父类不能依赖子类,它们都要依赖于抽象类)

2.抽象不能依赖于具体,具体应该要依赖于抽象。

注意,这里的接口不是狭义的接口

为什么要依赖接口?因为接口体现对问题的抽象,同时由于抽象一般是相对稳定的或者是相对变化不频繁的,而具体是易变的。因此依赖抽象是实现代码扩展和运行期内绑定(多态)的基础:只要实现了该抽象类的子类,都可以被类的使用都使用。这里,强调一下扩展性这个概念。通常扩展性指对已知行为的扩展,在讲述接口时,也提到过,接口应该是相对的。这就告诉我们,无论使用多么先进的设计模式,也无法做到不需要修改代码即可达到不变应万变的地上。在面向对象的这五大原则里,我认为依赖倒置是最难理解,也是最难实现的。

这里以雇员类为例

<?php
interface employee
{
  public function working();
}
class teacher implements employee
{
  public function working()
  {
    echo 'teaching...';
  }
}
class coder implements employee
{
  public function working()
  {
    echo 'coding...';
  }
}
class workA
{
  public function work()
  {
    $teacher = new teacher();
    $teacher->working();
  }
}
class workB
{
  private $e;
  public function set(employee $e)
  {
    $this->e = $e;
  }
  public function work()
  {
    $this->e->working();
  }
}
$worka = new workA;
$worka->work();
$workb = new workB;
$workb->set(new teacher());
$workb->work();

在workA中,work方法依赖于teacher实现;在workB中,work转而依赖抽象,这样可以把需要的对象通过参数传入。上述代码通过接口,实现了一定程度的解耦,但仍然是有限的。不仅是使用接口,使用工厂等也能实现一定程度的解耦和依赖倒置。

在workB中,teacher实例通过set方法传入,从而实现了工厂模式。由于这样的实现仍然是硬编码的,为了实现代码的进一步扩展,把这个依赖关系写在配置文件里,指明workB需要一个teacher对象,专门由一个程序配置是否正确(如所依赖的类文件是否存在)以及加载配置中所依赖的实现,这个检测程序,就称为IOC容器。

很多文章里看到IOC(Inversion of Control)概念,实际上,IOC是依赖倒置原则(Dependence Inversion Principle,DIP)的同义词。而在提IOC的时候,你可能还会看到有人提起DI等概念。DI,即依赖注入,一般认为,依赖注入(DI)和依赖查找(DS)是IOC的两种实现。不过随着某些概论的演化,这几个概念之间的关系也变得很模糊,也有人认为IOC就是DI。有人认为,依赖注入的描述比起IOC来更贴切,这里不纠缠于这几个概念之间的关系。

在经典的J2EE设计里,通常把DAO层和Servicen层细分为接口层和实现层,然后在配置文件里进行所依赖关系的配置,这是最常见的DIP的应用。Spring框架就是一个很好的IOC容器,把控制权从代码剥离到IOC窗口,这里是通过XML配置文件实现的,Spring在执行期间根据配置文件的设定,建立对象之间的依赖关系。

如下面的代码所示

<bean scopre="prototype" class="cn.notebook.action.NotebookListOtherAction" id="notebookListOtherAction">
  <property ref="userReplyService" name="userReplyService" />
  <property ref="userService" name="userService" />
  <property ref="permissionService" name="permissionService" />
  <property ref="friendService" name="friendService" />
</bean>

但是这样的设置一样存在问题,配置文件会变得越来越大,其间关系会越来越复杂。同样逃脱不了随着应用和业务的改变,不断修改代码的恶魇(这里认为配置文件是代码的一部分。并且在实际开发中,很少存在单纯修改配置文件的情况。一般配置文件修改了,代码也会做相应的修改)

在PHP里,也有类似模仿Spring的实现,即把依赖关系写在了配置文件里,通过配置文件来产生需要的对象。我觉得这样的代码还是为了实现而实现。在Srping里,配置文件里配置的不仅仅是一个类运行时的依赖关系,还可以实现事务管理、AOP、延迟加载等。而PHP要实现上面的种种特性,其消耗是巨大的。从语言层面讲,PHP这种动态脚本语言在实现一些多态特性上和编译型的语言不同。其次PHP作为敏捷性的开发语言,更强调快速开发、逻辑清晰、代码更简单易懂,如果再附加了各种设计模式的框架,从技术实现和运行效率上来看,都是不可取的。依赖倒置的核心原则是解耦。如果脱离这个最原始的原则,那就是本末倒置。

事实上,很多的设计模式里已经隐含了依赖倒置原则我们也在有意无意地做着一些依赖反转的工作。只是作为PHP,目前还没有一个比较完善的IOC容器,或许是PHP根本不需要。

如果满足DIP:

1.每个较高层次类都为它所需要的服务提出一个接口声明,较低层次类实现实现这个接口。

2.每个高层次类都通过该抽象接口使用服务。

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

PHP 相关文章推荐
PHP 简单日历实现代码
Oct 28 PHP
php的chr和ord函数实现字符加减乘除运算实现代码
Dec 05 PHP
php中使用接口实现工厂设计模式的代码
Jun 17 PHP
遭遇php的in_array低性能问题
Sep 17 PHP
php验证手机号码
Nov 11 PHP
php创建桌面快捷方式实现方法
Dec 31 PHP
PHP常用字符串操作函数实例总结(trim、nl2br、addcslashes、uudecode、md5等)
Jan 09 PHP
PHP.vs.JAVA
Apr 29 PHP
CI框架常用方法小结
May 17 PHP
php微信公众平台开发(一) 配置接口
Dec 06 PHP
PHP中危险的file_put_contents函数详解
Nov 04 PHP
Laravel (Lumen) 解决JWT-Auth刷新token的问题
Oct 24 PHP
PHP面向对象五大原则之里氏替换原则(LSP)详解
Apr 08 #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
You might like
php字符串截取问题
2006/11/28 PHP
yii框架配置默认controller和action示例
2014/04/30 PHP
ThinkPHP 404页面的设置方法
2015/01/14 PHP
详解PHP用substr函数截取字符串中的某部分
2016/12/03 PHP
Javascript 读书笔记索引贴
2010/01/11 Javascript
新鲜出炉的js tips提示效果
2011/04/03 Javascript
JS通过相同的name进行表格求和代码
2013/08/18 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
JS实现简单路由器功能的方法
2015/05/27 Javascript
JQuery给select添加/删除节点的实现代码
2016/04/26 Javascript
jQuery获取剪贴板内容的方法
2016/06/16 Javascript
JS使用正则实现去掉字符串左右空格的方法
2016/12/27 Javascript
微信小程序商城项目之商品属性分类(4)
2017/04/17 Javascript
10个在JavaScript开发中常遇到的BUG
2017/12/18 Javascript
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
手把手教你写一个微信小程序(推荐)
2018/10/17 Javascript
浅谈发布订阅模式与观察者模式
2019/04/09 Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
2019/05/30 Javascript
[03:55]显微镜下的DOTA2特别篇——430灰烬之灵神级操作
2014/06/24 DOTA
[02:05]2014DOTA2国际邀请赛 BBC外卡赛赛后总结
2014/07/09 DOTA
Python获取当前公网ip并自动断开宽带连接实例代码
2018/01/12 Python
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
Python常用模块之requests模块用法分析
2019/05/15 Python
PyQt5使用QTimer实现电子时钟
2019/07/29 Python
Python 求数组局部最大值的实例
2019/11/26 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
2020/03/11 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
用Python开发app后端有优势吗
2020/06/29 Python
Python3 用matplotlib绘制sigmoid函数的案例
2020/12/11 Python
Maxpeedingrods美国:高性能汽车零件
2020/02/14 全球购物
Booking.com德国:预订最好的酒店和住宿
2020/02/16 全球购物
大学生毕业求职找工作的自我评价
2013/09/29 职场文书
文明和谐家庭事迹材料
2014/05/18 职场文书
项目经理任命书范本
2014/06/05 职场文书
寒暑假实习证明书模板
2014/11/29 职场文书
浅谈MySql整型索引和字符串索引失效或隐式转换问题
2021/11/20 MySQL