php中Ioc(控制反转)和Di(依赖注入)


Posted in PHP onMay 07, 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变量和$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 相关文章推荐
phpExcel导出大量数据出现内存溢出错误的解决方法
Feb 28 PHP
PHP代码审核的详细介绍
Jun 13 PHP
PHP循环结构实例讲解
Feb 10 PHP
深入探究PHP的多进程编程方法
Aug 18 PHP
详解WordPress中提醒安装插件以及隐藏插件的功能实现
Dec 25 PHP
CodeIgniter视图使用注意事项
Jan 20 PHP
PHP实现的简单分页类及用法示例
May 06 PHP
php for 循环使用的简单实例
Jun 02 PHP
Yii2实现同时搜索多个字段的方法
Aug 10 PHP
PHP实现二维数组根据key进行排序的方法
Dec 30 PHP
ThinkPHP框架整合微信支付之刷卡模式图文详解
Apr 10 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
Mar 23 PHP
Laravel中任务调度console使用方法小结
May 07 #PHP
Laravel实现表单提交
May 07 #PHP
Laravel实现autoload方法详解
May 07 #PHP
PHP中include和require的区别实例分析
May 07 #PHP
自制PHP框架之设计模式
May 07 #PHP
自制PHP框架之模型与数据库
May 07 #PHP
自制PHP框架之路由与控制器
May 07 #PHP
You might like
自己做矿石收音机
2021/03/02 无线电
PHP判断远程url是否有效的几种方法小结
2011/10/08 PHP
php查找任何页面上的所有链接的方法
2013/12/03 PHP
PHP常用函数和常见疑难问题解答
2014/03/05 PHP
PHP扩展程序实现守护进程
2015/04/16 PHP
PHP的Yii框架中Model模型的学习教程
2016/03/29 PHP
图文详解PHP环境搭建教程
2016/07/16 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
Javascript学习笔记6 prototype的提出
2010/01/11 Javascript
jquery入门——事件机制之事件中的冒泡现象示例解释
2020/09/12 Javascript
AngularJS中的模块详解
2015/01/29 Javascript
JavaScript创建闭包的两种方式的优劣与区别分析
2015/06/22 Javascript
jquery合并表格中相同文本的相邻单元格
2015/07/17 Javascript
js判断当前页面用什么浏览器打开的方法
2016/01/06 Javascript
jquery.validate 自定义验证方法及validate相关参数
2016/01/18 Javascript
jQuery中弹出iframe内嵌页面元素到父页面并全屏化的实例代码
2016/12/27 Javascript
js 用于检测类数组对象的函数方法
2017/05/02 Javascript
javascript 作用于作用域链的详解
2017/09/27 Javascript
Vue2 SSR渲染根据不同页面修改 meta
2017/11/20 Javascript
JavaScript学习笔记之DOM基础操作实例小结
2019/01/09 Javascript
ES2020 新特性(种草)
2020/01/12 Javascript
vue实现图书管理系统
2020/12/29 Vue.js
[50:34]VGJ.T vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
python实现QQ空间自动点赞功能
2019/04/09 Python
Python虚拟环境的创建和包下载过程分析
2020/06/19 Python
基于Pytorch版yolov5的滑块验证码破解思路详解
2021/02/25 Python
REN Clean Skincare官网:英国本土有机护肤品牌
2019/02/23 全球购物
FORZIERI福喜利中国官网:奢侈品购物梦工厂
2019/05/03 全球购物
英国排名第一的餐具品牌:Denby Pottery
2019/11/01 全球购物
澳大利亚家用电器在线商店:Billy Guyatts
2020/05/05 全球购物
经济管理专业求职信
2014/06/09 职场文书
沙滩主题婚礼活动策划方案
2014/09/15 职场文书
红色革命电影观后感
2015/06/18 职场文书
小学秋季运动会通讯稿
2015/11/25 职场文书
MySQL新手入门进阶语句汇总
2022/09/23 MySQL