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操作MongoDB时的整数问题及对策说明
May 02 PHP
PHP中其实也可以用方法链
Nov 10 PHP
PHP命名空间(Namespace)的使用详解
May 04 PHP
PHP函数分享之curl方式取得数据、模拟登陆、POST数据
Jun 04 PHP
php字符串截取函数用法分析
Nov 25 PHP
php将数组转换成csv格式文件输出的方法
Mar 14 PHP
windows下apache搭建php开发环境
Aug 27 PHP
php 判断过去离现在几年的函数(实例代码)
Nov 15 PHP
PHP接口并发测试的方法(推荐)
Dec 15 PHP
对laravel in 查询的使用方法详解
Oct 09 PHP
Laravel框架控制器,视图及模型操作图文详解
Dec 04 PHP
Laravel5.1 框架Request请求操作常见用法实例分析
Jan 04 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 过滤危险html代码
2009/06/29 PHP
PHP验证码生成原理和实现
2016/01/24 PHP
PHP二维数组排序简单实现方法
2016/02/14 PHP
php使用escapeshellarg时中文被过滤的解决方法
2016/07/10 PHP
PHP hebrev()函数用法讲解
2019/02/21 PHP
php ajax confirm 删除实例详解
2019/03/06 PHP
php与阿里云短信接口接入操作案例分析
2020/05/27 PHP
浅析javascript闭包 实例分析
2010/12/25 Javascript
JS之Date对象和获取系统当前时间详解
2014/01/13 Javascript
Jquery操作js数组及对象示例代码
2014/05/11 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
2014/07/17 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
Bootstrap选项卡学习笔记分享
2017/02/13 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
2017/07/11 Javascript
js+html5实现复制文字按钮
2017/07/15 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
使用vuex的state状态对象的5种方式
2018/04/19 Javascript
vue请求数据的三种方式
2020/03/04 Javascript
uni-app如何页面传参数的几种方法总结
2020/04/28 Javascript
深入了解Vue3模板编译原理
2020/11/19 Vue.js
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
[01:27:30]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Python结合ImageMagick实现多张图片合并为一个pdf文件的方法
2018/04/24 Python
python3实现SMTP发送邮件详细教程
2018/06/19 Python
Python3的介绍、安装和命令行的认识(推荐)
2018/10/20 Python
python em算法的实现
2020/10/03 Python
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
个人实用的自我评价范文
2013/11/23 职场文书
大学生职业生涯规划范文
2014/01/08 职场文书
书法比赛获奖感言
2014/02/10 职场文书
政治学求职信
2014/06/03 职场文书
医学专业毕业生求职信
2014/06/20 职场文书
幼儿园推普周活动总结
2015/05/07 职场文书
三方合作意向书范本
2015/05/09 职场文书
2015年社区教育工作总结
2015/05/13 职场文书