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 09 PHP
PHP4中实现动态代理
Oct 09 PHP
php 遍历数据表数据并列表横向排列的代码
Sep 05 PHP
解析二进制流接口应用实例 pack、unpack、ord 函数使用方法
Jun 18 PHP
PHP中对各种加密算法、Hash算法的速度测试对比代码
Jul 08 PHP
PHP用正则匹配form表单中所有元素的类型和属性值实例代码
Feb 28 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
Apr 23 PHP
php和asp语法上的区别总结
May 12 PHP
PHP经典设计模式之依赖注入定义与用法详解
May 21 PHP
laravel 操作数据库常用函数的返回值方法
Oct 11 PHP
php 命名空间(namespace)原理与用法实例小结
Nov 13 PHP
TP5框架使用QueryList采集框架爬小说操作示例
Mar 26 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/19 PHP
php创建多级目录代码
2008/06/05 PHP
php 运行效率总结(提示程序速度)
2009/11/26 PHP
关于session在PHP5的配置文件中的详细设置参数说明
2011/04/20 PHP
如何使用PHP批量去除文件UTF8 BOM信息
2013/08/05 PHP
php目录操作实例代码
2014/02/21 PHP
PHP人民币金额转大写实例代码
2015/10/02 PHP
javascript的内存管理详解
2013/08/07 Javascript
window.open打开页面居中显示的示例代码
2013/12/27 Javascript
JS使用ajax方法获取指定url的head信息中指定字段值的方法
2015/03/24 Javascript
Angular动态添加、删除输入框并计算值实例代码
2017/03/29 Javascript
jQuery Validate 校验多个相同name的方法
2017/05/18 jQuery
详解express + mock让前后台并行开发
2018/06/06 Javascript
使用webpack构建应用的方法步骤
2019/03/04 Javascript
微信小程序实现文件、图片上传功能
2020/08/18 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
jquery.validate自定义验证用法实例分析【成功提示与择要提示】
2020/06/06 jQuery
Python里隐藏的“禅”
2014/06/16 Python
Python3一行代码实现图片文字识别的示例
2018/01/15 Python
Python后台开发Django的教程详解(启动)
2019/04/08 Python
Python如何实现定时器功能
2020/05/28 Python
Python如何输出整数
2020/06/07 Python
python爬虫使用requests发送post请求示例详解
2020/08/05 Python
8款精美的CSS3表单设计(登录表单/下拉选择/按钮附演示及源码)
2013/02/04 HTML / CSS
Beauty Expert美国/加拿大:购买奢侈美容产品
2018/12/05 全球购物
护理专业自荐信
2013/12/03 职场文书
销售实习自我鉴定
2013/12/07 职场文书
教师党员个人整改措施材料
2014/09/16 职场文书
学生抄袭作业的检讨书
2014/10/02 职场文书
开展党的群众路线教育实践活动个人对照检查材料
2014/11/05 职场文书
2015年骨干教师工作总结
2015/05/26 职场文书
党支部鉴定意见
2015/06/02 职场文书
食堂卫生管理制度
2015/08/04 职场文书
2019生态环境保护倡议书!
2019/07/03 职场文书
「SHOW BY ROCK!!」“雫シークレットマインド”组合单曲MV公开
2022/03/21 日漫
Win11任务栏无法正常显示 资源管理器不停重启的解决方法
2022/07/07 数码科技