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的库,结果发现很多东西
Dec 31 PHP
解析posix与perl标准的正则表达式区别
Jun 17 PHP
table标签的结构与合并单元格的实现方法
Jul 24 PHP
PHP+MySQL之Insert Into数据插入用法分析
Sep 27 PHP
php编程中echo用逗号和用点号连接的区别
Mar 26 PHP
php自定义截取中文字符串-utf8版
Feb 27 PHP
PHP随机获取未被微信屏蔽的域名(微信域名检测)
Mar 19 PHP
PHP按符号截取字符串的指定部分的实现方法
Sep 10 PHP
PHP操作路由器实现方法示例
Apr 27 PHP
PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】
Jun 14 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
Sep 12 PHP
laravel5.5添加echarts实现画图功能的方法
Oct 09 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防止sql注入小技巧之sql预处理原理与实现方法分析
2019/12/13 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
prototype与jquery下Ajax实现的差别
2009/09/13 Javascript
JS 实现完美include载入实现代码
2010/08/05 Javascript
基于jQuery的简单九宫格实现代码
2012/08/09 Javascript
JavaScript 数组详解
2013/10/10 Javascript
三种检测iPhone/iPad设备方向的方法
2014/04/23 Javascript
JS继承用法实例分析
2015/02/05 Javascript
基于jquery实现鼠标滚轮驱动的图片切换效果
2015/10/26 Javascript
vue.js移动端app之上拉加载以及下拉刷新实战
2017/09/11 Javascript
js + css实现标签内容切换功能(实例讲解)
2017/10/09 Javascript
JavaScript 日期时间选择器一些小结
2018/04/02 Javascript
vue和webpack项目构建过程常用的npm命令详解
2018/06/15 Javascript
Vue和React组件之间的传值方式详解
2019/01/31 Javascript
jQuery-Citys省市区三级菜单联动插件使用详解
2019/07/26 jQuery
Element实现表格嵌套、多个表格共用一个表头的方法
2020/05/09 Javascript
vue绑定数字类型 value为数字的实例
2020/08/31 Javascript
wxPython中文教程入门实例
2014/06/09 Python
基于DATAFRAME中元素的读取与修改方法
2018/06/08 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
基于python调用psutil模块过程解析
2019/12/20 Python
pytorch 求网络模型参数实例
2019/12/30 Python
Python实现对adb命令封装
2020/03/06 Python
Python 绘制可视化折线图
2020/07/22 Python
python实现canny边缘检测
2020/09/14 Python
瑞典时尚服装购物网站:Miinto.se
2017/10/30 全球购物
简单租房协议书
2014/04/09 职场文书
文案策划专业自荐信
2014/07/07 职场文书
党支部创先争优活动总结
2014/08/28 职场文书
单位委托书范本(3篇)
2014/09/18 职场文书
故宫英文导游词
2015/01/31 职场文书
护理专业自荐信范文
2015/03/06 职场文书
劳动仲裁撤诉申请书
2015/05/18 职场文书
八年级语文教学反思
2016/03/03 职场文书
CSS3实现的文字弹出特效
2021/04/16 HTML / CSS
深入浅析React中diff算法
2021/05/19 Javascript