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 相关文章推荐
Classes and Objects in PHP5-面向对象编程 [1]
Oct 09 PHP
php array_merge下进行数组合并的代码
Jul 22 PHP
php数组函数序列之array_flip() 将数组键名与值对调
Nov 07 PHP
Codeigniter实现智能裁剪图片的方法
Jun 12 PHP
php专用数组排序类ArraySortUtil用法实例
Apr 03 PHP
php实现图片等比例缩放代码
Jul 23 PHP
php上传图片生成缩略图(GD库)
Jan 06 PHP
PHP实现的限制IP投票程序IP来源分析
May 04 PHP
php+mysql查询实现无限下级分类树输出示例
Oct 03 PHP
静态html文件执行php语句的方法(推荐)
Nov 21 PHP
详解thinkphp中的volist标签
Jan 15 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 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
destoon实现不同会员组公司名称显示不同的颜色的方法
2014/08/22 PHP
PHP扩展开发入门教程
2015/02/26 PHP
php 中奖概率算法实现代码
2017/01/25 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
彻底搞懂JS无缝滚动代码
2007/01/03 Javascript
记录几个javascript有关的小细节
2007/04/02 Javascript
基于jQuery捕获超链接事件进行局部刷新代码
2012/05/10 Javascript
jQuery中对节点进行操作的相关介绍
2013/04/16 Javascript
js+css实现增加表单可用性之提示文字
2013/06/03 Javascript
js 弹出框只弹一次(二次修改之后的)
2013/11/26 Javascript
jQuery $.each遍历对象、数组用法实例
2015/04/16 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
使用jquery.form.js实现图片上传的方法
2016/05/05 Javascript
jquery中用函数来设置css样式
2016/12/22 Javascript
jQuery Masonry瀑布流插件使用方法详解
2017/01/18 Javascript
Vue.js实现一个漂亮、灵活、可复用的提示组件示例
2017/03/17 Javascript
vue-devtools的安装步骤
2018/04/23 Javascript
vue.js多页面开发环境搭建过程
2019/04/24 Javascript
easyUI 实现的后台分页与前台显示功能示例
2020/06/01 Javascript
vue实现点击按钮“查看详情”弹窗展示详情列表操作
2020/09/09 Javascript
js实现手表表盘时钟与圆周运动
2020/09/18 Javascript
vue+vant实现购物车全选和反选功能
2020/11/17 Vue.js
Python help()函数用法详解
2014/03/11 Python
Python三元运算实现方法
2015/01/12 Python
在Python中操作时间之mktime()方法的使用教程
2015/05/22 Python
详解Python的Django框架中inclusion_tag的使用
2015/07/21 Python
详解Python中的元组与逻辑运算符
2015/10/13 Python
使用Nginx+uWsgi实现Python的Django框架站点动静分离
2016/03/21 Python
PyCharm安装第三方库如Requests的图文教程
2018/05/18 Python
Pandas库之DataFrame使用的学习笔记
2019/06/21 Python
css3实现文字扫光渐变动画效果的示例
2017/11/07 HTML / CSS
总裁秘书岗位职责
2013/12/04 职场文书
护理专业学生的求职信范文
2013/12/11 职场文书
一次性工伤赔偿协议书范本
2014/11/25 职场文书
安全保证书格式
2015/02/28 职场文书
详解Alibaba Java诊断工具Arthas查看Dubbo动态代理类
2022/04/08 Java/Android