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 相关文章推荐
5.PHP的其他功能
Oct 09 PHP
一个简单的自动发送邮件系统(三)
Oct 09 PHP
关于mysql 字段的那个点为是定界符
Jan 15 PHP
深入理解PHP原理之Session Gc的一个小概率Notice
Apr 12 PHP
php登陆页的密码处理方式分享
Oct 14 PHP
反射调用private方法实践(php、java)
Dec 21 PHP
Linux php 中文乱码的快速解决方法
May 13 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
Oct 08 PHP
PHP实现二维数组根据key进行排序的方法
Dec 30 PHP
PHP实现批量修改文件名的方法示例
Sep 18 PHP
解决php用mysql方式连接数据库出现Deprecated报错问题
Dec 25 PHP
TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析
Dec 31 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
在PHP3中实现SESSION的功能(一)
2006/10/09 PHP
用PHP控制用户的浏览器--ob*函数的使用说明
2007/03/16 PHP
深入php函数file_get_contents超时处理的方法详解
2013/06/03 PHP
PHP Class&amp;Object -- PHP 自排序二叉树的深入解析
2013/06/25 PHP
php修改上传图片尺寸的方法
2015/04/14 PHP
PHP7+Nginx的配置与安装教程详解
2016/05/10 PHP
YII2框架中excel表格导出的方法详解
2017/07/21 PHP
javascript中的注释使用与注意事项小结
2011/09/20 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
JavaScript学习笔记之JS对象
2015/01/22 Javascript
javascript中数组方法汇总
2015/07/07 Javascript
js实现文本框宽度自适应文本宽度的方法
2015/08/13 Javascript
JavaScript中的对象继承关系
2016/08/01 Javascript
jQuery使用animate实现ul列表项相互飘动效果示例
2016/09/16 Javascript
javascript实现去除HTML标签的方法
2016/12/26 Javascript
微信小程序图表插件(wx-charts)实例代码
2017/01/17 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
2017/04/21 jQuery
vue.extend与vue.component的区别和联系
2018/09/19 Javascript
jquery实现点击弹出对话框
2020/02/08 jQuery
vue-simple-uploader上传成功之后的response获取代码
2020/09/07 Javascript
[00:17]天涯墨客一技能展示
2018/08/25 DOTA
Python中的魔法方法深入理解
2014/07/09 Python
python 执行shell命令并将结果保存的实例
2018/05/11 Python
Python统计python文件中代码,注释及空白对应的行数示例【测试可用】
2018/07/25 Python
python设置随机种子实例讲解
2019/09/12 Python
ALDO英国官网:加拿大女鞋品牌
2018/02/19 全球购物
美国在线打印网站:Overnight Prints
2018/10/11 全球购物
橄榄树药房:OLIVEDA
2019/09/01 全球购物
JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
2015/10/22 面试题
护士求职信
2014/07/05 职场文书
解放思想大讨论活动心得体会
2014/09/11 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
幼儿园大班教师个人工作总结
2015/02/05 职场文书
mysql 联合索引生效的条件及索引失效的条件
2021/11/20 MySQL
Java异常处理try catch的基本用法
2021/12/06 Java/Android
一文搞清楚MySQL count(*)、count(1)、count(col)区别
2022/03/03 MySQL