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的类树(支持无限分类)
Oct 09 PHP
用PHP中的 == 运算符进行字符串比较
Nov 26 PHP
模拟flock实现文件锁定
Feb 14 PHP
PHP 函数执行效率的小比较
Oct 17 PHP
php中计算中文字符串长度、截取中文字符串的函数代码
Aug 09 PHP
PHP中获取文件扩展名的N种方法小结
Feb 27 PHP
php设计模式之观察者模式的应用详解
May 21 PHP
ThinkPHP独立分组使用的注意事项
Nov 25 PHP
PHP实现的memcache环形队列类实例
Jul 28 PHP
YII Framework框架教程之缓存用法详解
Mar 14 PHP
php正则提取html图片(img)src地址与任意属性的方法
Feb 08 PHP
php pdo连接数据库操作示例
Nov 18 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
详解WordPress中给链接添加查询字符串的方法
2015/12/18 PHP
PHP实现APP微信支付的实例讲解
2018/02/10 PHP
php使用redis的有序集合zset实现延迟队列应用示例
2020/02/20 PHP
PHP执行系统命令函数实例讲解
2021/03/03 PHP
jquery二级导航内容均分的原理及实现
2013/08/13 Javascript
JavaScript数组常用方法
2015/03/02 Javascript
javascript中indexOf技术详解
2015/05/07 Javascript
js时钟翻牌效果实现代码分享
2020/07/31 Javascript
Jquery on方法绑定事件后执行多次的解决方法
2016/06/02 Javascript
JavaScript 对象字面量讲解
2016/06/06 Javascript
正则中的回溯定义与用法分析【JS与java实现】
2016/12/27 Javascript
bootstrap daterangepicker双日历时间段选择控件详解
2017/06/15 Javascript
详解react-redux插件入门
2018/04/19 Javascript
seajs下require书写约定实例分析
2018/05/16 Javascript
Node.js进阶之核心模块https入门
2018/05/23 Javascript
微信小程序排坑指南详解
2018/05/23 Javascript
js 实现在2d平面上画8的方法
2018/10/10 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
2020/02/15 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
2020/02/26 Javascript
flask中使用蓝图将路由分开写在不同文件实例解析
2018/01/19 Python
Django给admin添加Action的步骤详解
2019/05/01 Python
python脚本开机自启的实现方法
2019/06/28 Python
Python求解正态分布置信区间教程
2019/11/20 Python
django之导入并执行自定义的函数模块图解
2020/04/01 Python
基于python和flask实现http接口过程解析
2020/06/15 Python
Python类及获取对象属性方法解析
2020/06/15 Python
Python函数调用追踪实现代码
2020/11/27 Python
史泰博(Staples)中国官方网站:办公用品一站式采购
2016/09/05 全球购物
部队领导证婚词
2014/01/12 职场文书
集中采购方案
2014/06/10 职场文书
2014年应急管理工作总结
2014/11/26 职场文书
酒店圣诞节活动总结
2015/05/06 职场文书
学雷锋团日活动总结
2015/05/06 职场文书
金正昆讲礼仪观后感
2015/06/11 职场文书
用 Python 元类的特性实现 ORM 框架
2021/05/19 Python
PHP设计模式(观察者模式)
2021/07/07 PHP