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函数,php爱好者站推荐
Mar 19 PHP
PHP 最大运行时间 max_execution_time修改方法
Mar 08 PHP
php5 non-thread-safe和thread-safe这两个版本的区别分析
Mar 13 PHP
php中Smarty模板初体验
Aug 08 PHP
PHP 面向对象程序设计(oop)学习笔记 (五) - PHP 命名空间
Jun 12 PHP
PHP缓存机制Output Control详解
Jul 14 PHP
基于ThinkPHP实现批量删除
Dec 18 PHP
在php中设置session用memcache来存储的方法总结
Jan 14 PHP
Zend Framework教程之模型Model基本规则和使用方法
Mar 04 PHP
PHP实现四种基础排序算法的运行时间比较(推荐)
Aug 11 PHP
PHP串行化与反串行化实例分析
Dec 27 PHP
PHP实现正则匹配所有括号中的内容
Jun 22 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 strcmp使用说明
2010/04/22 PHP
PHP取整数函数常用的四种方法小结
2012/07/05 PHP
php计算给定时间之前的函数用法实例
2015/04/03 PHP
Symfony学习十分钟入门经典教程
2016/02/03 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
PHP PDOStatement::execute讲解
2019/01/31 PHP
PHP 7.4中使用预加载的方法详解
2019/07/08 PHP
php变量与字符串的增删改查操作示例
2020/05/07 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
js实现的网站首页随机公告随机公告
2007/03/14 Javascript
JSON序列化与解析原生JS方法且IE6和chrome测试通过
2013/09/05 Javascript
jQuery实现点击行选中或取消CheckBox的方法
2016/08/01 Javascript
微信小程序用户信息encryptedData详解
2018/08/24 Javascript
微信小程序实现列表的横向滑动方式
2020/07/15 Javascript
JS实现小米轮播图
2020/09/21 Javascript
[33:39]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第二局
2016/02/27 DOTA
python的numpy模块安装不成功简单解决方法总结
2017/12/23 Python
Python实现爬取亚马逊数据并打印出Excel文件操作示例
2019/05/16 Python
Python中print函数简单使用总结
2019/08/05 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
python3爬虫中异步协程的用法
2020/07/10 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
python实现图片,视频人脸识别(opencv版)
2020/11/18 Python
input file上传文件样式支持html5的浏览器解决方案
2012/11/14 HTML / CSS
Currentbody法国:健康与美容高科技产品
2020/08/16 全球购物
商得四方公司面试题(gid+)
2014/04/30 面试题
优秀部门获奖感言
2014/02/14 职场文书
人力资源部经理助理岗位职责
2014/03/04 职场文书
临床护理求职信
2014/04/26 职场文书
化工操作工岗位职责
2014/04/29 职场文书
小班上学期评语
2014/05/05 职场文书
经理助理岗位职责
2015/02/02 职场文书
学校财务管理制度
2015/08/04 职场文书
golang 比较浮点数的大小方式
2021/05/02 Golang
浅谈Python协程asyncio
2021/06/20 Python
Python内置类型集合set和frozenset的使用详解
2022/04/26 Python