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 相关文章推荐
PHP4 与 MySQL 交互使用
Oct 09 PHP
附件名前加网站名
Mar 23 PHP
Php图像处理类代码分享
Jan 19 PHP
推荐25款php中非常有用的类库
Sep 29 PHP
Thinkphp搜索时首页分页和搜索页保持条件分页的方法
Dec 05 PHP
php输出全球各个时区列表的方法
Mar 31 PHP
PHP扩展框架之Yaf框架的安装与使用
May 18 PHP
php 在字符串指定位置插入新字符的简单实现
Jun 28 PHP
ThinkPHP实现静态缓存和动态缓存示例代码
May 02 PHP
弹出模态框modal的实现方法及实例
Sep 19 PHP
PHP简单实现欧拉函数Euler功能示例
Nov 06 PHP
php爬取天猫和淘宝商品数据
Feb 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
2020最新CPU的性能排名
2020/04/02 数码科技
php文件上传简单实现方法
2015/01/24 PHP
PHP文件读取功能的应用实例
2015/05/08 PHP
在thinkphp5.0路径中实现去除index.php的方式
2019/10/16 PHP
jQuery实现表头固定效果的实例代码
2013/05/24 Javascript
jQuery 如何先创建、再修改、后添加DOM元素
2014/05/20 Javascript
分享20个提升网站界面体验的jQuery插件
2014/12/15 Javascript
JavaScript中setFullYear()方法的使用详解
2015/06/11 Javascript
JavaScript模拟实现键盘打字效果
2015/06/29 Javascript
使用jQuery获取data-的自定义属性
2015/11/10 Javascript
快速使用node.js进行web开发详解
2017/04/26 Javascript
微信小程序 开发MAP(地图)实例详解
2017/06/27 Javascript
如何理解Vue的.sync修饰符的使用
2017/08/17 Javascript
JS设计模式之惰性模式(二)
2017/09/29 Javascript
浅谈vue路径优化之resolve
2017/10/13 Javascript
在vue中通过axios异步使用echarts的方法
2018/01/13 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
原生js canvas实现鼠标跟随效果
2020/08/02 Javascript
VsCode里的Vue模板的实现
2020/08/12 Javascript
Python制作exe文件简单流程
2019/01/24 Python
用Python配平化学方程式的方法
2019/07/20 Python
pytorch 模型可视化的例子
2019/08/17 Python
如何基于Python获取图片的物理尺寸
2019/11/25 Python
TensorFlow2.0:张量的合并与分割实例
2020/01/19 Python
完美解决ARIMA模型中plot_acf画不出图的问题
2020/06/04 Python
python 如何实现遗传算法
2020/09/22 Python
python-图片流传输的思路及示例(url转换二维码)
2020/12/21 Python
JACK & JONES英国官方网站:欧洲领先的男装生产商
2017/09/27 全球购物
几个MySql的面试题
2013/04/22 面试题
没有孩子的离婚协议书怎么写
2014/09/17 职场文书
高考诚信考试承诺书
2015/04/29 职场文书
家装电话营销开场白
2015/05/29 职场文书
2016年教师寒假学习心得体会
2015/10/09 职场文书
spring项目中切面及AOP的使用方法
2021/06/26 Java/Android
SpringBoot全局异常处理方案分享
2022/05/25 Java/Android