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 相关文章推荐
PHP中在数据库中保存Checkbox数据(2)
Oct 09 PHP
PHP 显示客户端IP与服务器IP的代码
Oct 12 PHP
php中使用explode查找某个字符是否存在的方法
Jul 12 PHP
简单实用的.net DataTable导出Execl
Oct 28 PHP
7个鲜为人知却非常实用的PHP函数
Jul 01 PHP
PHP图片添加水印功能示例小结
Oct 03 PHP
PHP对XML内容进行修改和删除实例代码
Oct 26 PHP
Centos 6.5系统下编译安装PHP 7.0.13的方法
Dec 19 PHP
Yii2使用表单上传文件的实例代码
Aug 03 PHP
PHP registerXPathNamespace()函数讲解
Feb 03 PHP
Laravel定时任务的每秒执行代码
Oct 22 PHP
PHP dirname简单使用代码实例
Nov 13 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
php上传文件的增强函数
2010/07/21 PHP
基于PHP array数组的教程详解
2013/06/05 PHP
php通过session防url攻击方法
2014/12/10 PHP
Nigma vs Alliance BO5 第一场2.14
2021/03/10 DOTA
跨域表单提交状态的变相判断代码
2009/11/12 Javascript
JavaScript 页面编码与浏览器类型判断代码
2010/06/03 Javascript
用JavaScript实现动画效果的方法
2013/07/20 Javascript
jquery.post用法关于type设置问题补充
2014/01/03 Javascript
JQuery给元素绑定click事件多次执行的解决方法
2014/05/29 Javascript
javascript实现连续赋值
2015/08/10 Javascript
基于JavaScript实现手机短信按钮倒计时(超简单)
2015/12/30 Javascript
NodeJs——入门必看攻略
2016/06/27 NodeJs
js H5 canvas投篮小游戏
2016/08/18 Javascript
JQuery动态添加Select的Option元素实现方法
2016/08/29 Javascript
AngularJS用户选择器指令实例分析
2016/11/04 Javascript
js正则表达式验证密码强度【推荐】
2017/03/03 Javascript
JavaScript使用链式方法封装jQuery中CSS()方法示例
2017/04/07 jQuery
JS 判断某变量是否为某数组中的一个值的3种方法(总结)
2017/07/10 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
2017/09/18 Javascript
用vue构建多页面应用的示例代码
2017/09/20 Javascript
jquery获取select选中值的文本,并赋值给另一个输入框的方法
2018/08/21 jQuery
使用异步controller与jQuery实现卷帘式分页
2019/06/18 jQuery
js实现随机点名功能
2020/12/23 Javascript
Python如何import文件夹下的文件(实现方法)
2017/01/24 Python
浅谈对yield的初步理解
2017/05/29 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
Python逐行读取文件内容的方法总结
2020/02/14 Python
Python 如何查找特定类型文件
2020/08/17 Python
美国在线轮胎零售商:SimpleTire
2019/04/08 全球购物
培训讲师邀请函
2014/01/10 职场文书
学习党的群众路线剖析材料
2014/10/09 职场文书
工作汇报开头与结尾怎么写
2014/11/08 职场文书
2014年教师教学工作总结
2014/11/08 职场文书
2014年后备干部工作总结
2014/12/08 职场文书
文艺委员竞选稿
2015/11/19 职场文书
Python scrapy爬取起点中文网小说榜单
2021/06/13 Python