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 相关文章推荐
56.com视频采集接口程序(PHP)
Sep 22 PHP
新手学习PHP的一些基础知识分享
Jul 27 PHP
PHP中使用FFMPEG获取视频缩略图和视频总时长实例
May 04 PHP
php定时执行任务设置详解
Feb 06 PHP
php获取错误信息的方法
Jul 17 PHP
PHP入门教程之数学运算技巧总结
Sep 11 PHP
PHP目录操作实例总结
Sep 27 PHP
php使用ftp实现文件上传与下载功能
Jul 21 PHP
visual studio code 调试php方法(图文详解)
Sep 15 PHP
总结PHP内存释放以及垃圾回收
Mar 29 PHP
实例分析10个PHP常见安全问题
Jul 09 PHP
PHP+redis实现微博的推模型案例分析
Jul 10 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
PHPShop存在多个安全漏洞
2006/10/09 PHP
php中批量删除Mysql中相同前缀的数据表的代码
2011/07/01 PHP
浅谈PHP中的Trait使用方法
2019/03/22 PHP
PhpSpreadsheet设置单元格常用操作汇总
2020/11/13 PHP
Javascript技术技巧大全(五)
2007/01/22 Javascript
原生Js与jquery的多组处理, 仅展开一个区块的折叠效果
2011/01/09 Javascript
浅析JavaScript中的同名标识符优先级
2013/12/06 Javascript
我的Node.js学习之路(一)
2014/07/06 Javascript
jquery中map函数遍历数组用法实例
2015/05/18 Javascript
AngularJs Scope详解及示例代码
2016/09/01 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
2017/01/12 Javascript
微信小程序之数据双向绑定与数据操作
2017/05/12 Javascript
微信小程序 scroll-view实现锚点滑动的示例
2017/12/06 Javascript
JS基于for语句编写的九九乘法表示例
2018/01/04 Javascript
vue 中引用gojs绘制E-R图的方法示例
2018/08/24 Javascript
Vue组件间通信方法总结(父子组件、兄弟组件及祖先后代组件间)
2019/04/17 Javascript
浅谈vue-router路由切换 组件重用挖下的坑
2019/11/01 Javascript
微信小程序后端实现授权登录
2020/02/24 Javascript
vue样式穿透 ::v-deep的具体使用
2020/06/04 Javascript
Python实现partial改变方法默认参数
2014/08/18 Python
Python和perl实现批量对目录下电子书文件重命名的代码分享
2014/11/21 Python
python实现多线程暴力破解登陆路由器功能代码分享
2015/01/04 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
详解pyinstaller selenium python3 chrome打包问题
2019/10/18 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
Python pandas 列转行操作详解(类似hive中explode方法)
2020/05/18 Python
深入浅析css3 中display box使用方法
2015/11/25 HTML / CSS
美国知名艺术画网站:Art.com
2017/02/09 全球购物
荷兰度假屋租赁网站:Aan Zee
2020/02/28 全球购物
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
党员自我剖析材料范文
2014/10/06 职场文书
实习生辞职信范文
2015/03/02 职场文书
数据库连接池
2021/04/06 MySQL
python中super()函数的理解与基本使用
2021/08/30 Python
PC版《死亡搁浅导剪版》现已发售 展开全新的探险
2022/04/03 其他游戏