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 相关文章推荐
php 获取客户端的真实ip
Nov 30 PHP
PHP 登录完成后如何跳转上一访问页面
Jan 14 PHP
php中利用explode函数分割字符串到数组
Feb 08 PHP
PHP封装分页函数实现文本分页和数字分页
Oct 23 PHP
PHP解析目录路径的3个函数总结
Nov 18 PHP
yii中widget的用法
Dec 03 PHP
php中使用url传递数组的方法
Feb 11 PHP
PHP获取当前相对于域名目录的方法
Jun 26 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
Feb 04 PHP
基于CI框架的微信网页授权库示例
Nov 25 PHP
PHP常用排序算法实例小结【基本排序,冒泡排序,快速排序,插入排序】
Feb 07 PHP
Laravel框架搜索分页功能示例
Feb 01 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
php合并数组array_merge函数运算符加号与的区别
2008/10/31 PHP
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
PHP调用Webservice实例代码
2011/07/29 PHP
浅析php与数据库代码开发规范
2013/08/08 PHP
thinkPHP3.2简单实现文件上传的方法
2016/05/16 PHP
laravel框架关于搜索功能的实现
2018/03/15 PHP
PHP数组对象与Json转换操作实例分析
2019/10/22 PHP
JavaScript判断窗口是否最小化的代码(跨浏览器)
2010/08/01 Javascript
解决iframe的frameborder在chrome/ff/ie下的差异
2010/08/12 Javascript
表单切换,用回车键替换Tab健(不支持IE)
2011/07/20 Javascript
JavaScript高级程序设计 XML、Ajax 学习笔记
2011/09/10 Javascript
js 调用父窗口的具体实现代码
2013/07/15 Javascript
jquery自定义函数的多种方法
2014/01/09 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
JS实现密码框的显示密码和隐藏密码功能示例
2016/12/26 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
angular中ui calendar的一些使用心得(推荐)
2017/11/03 Javascript
jQuery分组选择器简单用法示例
2019/04/04 jQuery
vue中el-input绑定键盘按键(按键修饰符)
2020/07/22 Javascript
多种类型jQuery网页验证码插件代码实例
2021/01/09 jQuery
python编程开发之类型转换convert实例分析
2015/11/13 Python
老生常谈Python基础之字符编码
2017/06/14 Python
对django的User模型和四种扩展/重写方法小结
2019/08/17 Python
opencv之为图像添加边界的方法示例
2019/12/26 Python
详解如何通过H5(浏览器/WebView/其他)唤起本地app
2017/12/11 HTML / CSS
台湾东南旅游社网站:东南旅游
2019/02/11 全球购物
小学评语大全
2014/04/22 职场文书
党的群众路线教育学习材料
2014/05/12 职场文书
关工委先进个人事迹材料
2014/05/23 职场文书
2014年生产管理工作总结
2014/12/23 职场文书
幼儿园工作总结2015
2015/04/01 职场文书
公司员工体检通知
2015/04/21 职场文书
美丽心灵观后感
2015/06/01 职场文书
孙振耀退休感言
2015/08/01 职场文书
解决pytorch读取自制数据集出现过的问题
2021/05/31 Python
vue实现滑动解锁功能
2022/03/03 Vue.js