PHP控制反转(IOC)和依赖注入(DI)


Posted in PHP onMarch 13, 2017

先看一个例子:

<?php
class A
{
 public $b;
 public $c;
 public function A()
 {
  //TODO
 }
 public function Method()
 {
  $this->b=new B();
  $this->c=new C();
  $this->b->Method();
  $this->c->Method();
  //TODO
 }
}
class B
{
 public function B()
 {
  //TODO
 }
 public function Method()
 {
  //TODO
  echo 'b';
 }
}
class C
{
 public function C()
 {
  //TODO
 }
 public function Method()
 {
  //TODO
  echo 'c';
 }
}
$a=new A();
$a->Method();
?>

上面代码,我们很容易理解一句话:

A类依赖B类和C类

也就是说,如果今后开发过程中,要对B类或者C类修改,一旦涉及函数改名,函数参数数量变动,甚至整个类结构的调整,我们也要对A类做出相应的调整,A类的独立性丧失了,这在开发过程中是很不方便的,也就是我们说的“牵一发动全身”,如果两个类是两个人分别写的,矛盾往往就在这个时候产生了。。。

万一真的要改动B类和C类,有没有办法,可以不去改动或者尽量少改动A类的代码呢?这里要用到控制反转。

高层模块不应该依赖于底层模块,两个都应该依赖抽象。

控制反转(IOC)是一种思想,依赖注入(DI)是实施这种思想的方法。

第一种方法叫做:构造器注入(这种方法也不推荐用,但比不用要好)

class A
{
 public $b;
 public $c;
 public function A($b,$c)
 {
  $this->b=$b;
  $this->c=$c;
 }
 public function Method()
 {
  $this->b->Method();
  $this->c->Method();
 }
}

客户端类这样写:

$a=new A(new B(),new C());
$a->Method();

A类的构造器依赖B类和C类,通过构造器的参数传入,至少实现了一点,就是B类对象b和C类对象c的创建都移至了A类外,所以一旦B类和C类发生改动,A类无需做修改,只要在client类里改就可以了

假如有一天,我们需要扩充B类,做两个B类的子类

class B
{
 public function B()
 {
  //TODO
 }
 public function Method()
 {
  //TODO
  echo 'b';
 }
}
class B1 extends B
{
 public function B1()
 {
  //TODO
 }
 public function Method()
 {
  echo 'b1';
 }
}
class B2 extends B
{
 public function B2()
 {
  //TODO
 }
 public function Method()
 {
  echo 'b2';
 }
}

也很简单,客户端类这么写:

$a=new A(new B2(),new C());
$a->Method();

所以A类是不用关心B类到底有哪些个子类的,只要在客户端类关心就可以了。

第二种方法叫做:工厂模式注入(推荐使用)

class Factory
{
 public function Factory()
 {
  //TODO
 }
 public function create($s)
 {
  switch($s)
  {
   case 'B':
   {
    return new B();
    break;
   }
   case 'C':
   {
    return new C();
    break;
   }
   default:
   {
    return null;
    break;
   }
  }
 }
}

我们A类代码改为:

class A
{
 public $b;
 public $c;
 public function A()
 {
  //TODO
 }
 public function Method()
 {
  $f=new Factory();
  $this->b=$f->create('B');
  $this->c=$f->create('C');
  $this->b->Method();
  $this->c->Method();
  //TODO
 }
}

其实已经解耦了一小部分,至少如果B类和C类的构造函数要是发生变化,比如修改函数参数等,我们只需要改Factory类就可以了。

抽象不应该依赖于细节,细节应该依赖于抽象。

把B类和C类中的方法再抽象出来,做一个接口

interface IMethod
{
 public function Method();
}

这样,A类中的b变量和b变量和c变量就不再是一个具体的变量了,而是一个抽象类型的变量,不到运行那一刻,不知道他们的Method方式是怎么实现的。

class B implements IMethod
{
 public function B()
 {
  //TODO
 }
 public function Method()
 {
  //TODO
  echo 'b';
 }
}
class C implements IMethod
{
 public function C()
 {
  //TODO
 }
 public function Method()
 {
  //TODO
  echo 'c';
 }
}

总结几点:

1.我们把A类中的B类对象和C类对象的创建移至A类外

2.原本A类依赖B类和C类,现在变成了A依赖Factory,Factory依赖B和C。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

PHP 相关文章推荐
snoopy PHP版的网络客户端提供本地下载
Apr 15 PHP
php xml文件操作代码(一)
Mar 20 PHP
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
Dec 19 PHP
PHP下使用CURL方式POST数据至API接口的代码
Feb 14 PHP
windows环境下php配置memcache的具体操作步骤
Jun 09 PHP
php文件压缩之PHPZip类用法实例
Jun 18 PHP
解决nginx不支持thinkphp中pathinfo的问题
Jul 21 PHP
PHP中PDO的事务处理分析
Apr 07 PHP
php实现微信扫码支付
Mar 26 PHP
visual studio code 调试php方法(图文详解)
Sep 15 PHP
浅析PHP中的闭包和匿名函数
Dec 25 PHP
PHP实现常用排序算法的方法
Feb 05 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
Mar 13 #PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
Mar 13 #PHP
php解析mht文件转换成html的实例
Mar 13 #PHP
使用phpQuery获取数组的实例
Mar 13 #PHP
php获取linux命令结果的实例
Mar 13 #PHP
老生常谈PHP位运算的用途
Mar 12 #PHP
PHP巧妙利用位运算实现网站权限管理的方法
Mar 12 #PHP
You might like
探讨方法的重写(覆载)详解
2013/06/08 PHP
thinkPHP框架对接支付宝即时到账接口回调操作示例
2016/11/14 PHP
php实现数据库的增删改查
2017/02/26 PHP
基于php中echo用逗号和用点号的区别详解
2018/01/23 PHP
解决thinkphp5未定义变量会抛出异常,页面错误,请稍后再试的问题
2019/10/16 PHP
jQuery(1.3.2) 7行代码搞定跟随屏幕滚动的层
2009/05/21 Javascript
jquery中ajax学习笔记4
2011/10/16 Javascript
ASP.NET jQuery 实例17 通过使用jQuery validation插件校验ListBox
2012/02/03 Javascript
jquery实现智能感知连接外网搜索
2013/05/21 Javascript
Extjs实现进度条的两种便捷方式
2013/09/26 Javascript
js导出txt示例代码
2014/01/14 Javascript
如何将php数组或者对象传递给javascript
2014/03/20 Javascript
jquery自定义右键菜单、全选、不连续选择
2016/03/01 Javascript
详解Backbone.js框架中的模型Model与其集合collection
2016/05/05 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
javascript数据结构中栈的应用之符号平衡问题
2017/04/11 Javascript
12个非常有用的JavaScript技巧
2017/05/17 Javascript
ES6 中可以提升幸福度的小功能
2018/08/06 Javascript
vue2过滤器模糊查询方法
2018/09/16 Javascript
如何优雅地在vue中添加权限控制示例详解
2019/03/07 Javascript
[03:30]完美盛典趣味短片 CSGO2019年度名场面
2019/12/07 DOTA
深入理解Python中的元类(metaclass)
2015/02/14 Python
Python django实现简单的邮件系统发送邮件功能
2017/07/14 Python
Python3 replace()函数使用方法
2018/03/19 Python
Python实现的多进程和多线程功能示例
2018/05/29 Python
python requests 测试代理ip是否生效
2018/07/25 Python
python的turtle库使用详解
2019/05/10 Python
Python统计分析模块statistics用法示例
2019/09/06 Python
基于numpy中的expand_dims函数用法
2019/12/18 Python
html5中JavaScript removeChild 删除所有节点
2014/05/16 HTML / CSS
连卡佛中国官网:Lane Crawford中文站
2018/01/27 全球购物
网络文明传播志愿者活动方案
2014/08/20 职场文书
关于群众路线的心得体会
2014/11/05 职场文书
小区物业管理2015年度工作总结
2015/10/22 职场文书
祝福语集锦:给妹妹结婚的祝福语
2019/12/18 职场文书
Python 数据科学 Matplotlib图库详解
2021/07/07 Python