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 相关文章推荐
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
May 03 PHP
php中几种常见安全设置详解
Apr 06 PHP
php array_search() 函数使用
Apr 13 PHP
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
Apr 09 PHP
PHP 获取文件权限函数介绍
Jul 11 PHP
Yii框架关联查询with用法分析
Dec 02 PHP
Web程序工作原理详解
Dec 25 PHP
PHP中基本HTTP认证技巧分析
Mar 16 PHP
详解HTTP Cookie状态管理机制
Jan 14 PHP
PHP里面把16进制的图片数据显示在html的img标签上(实现方法)
May 02 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
Sep 16 PHP
PHP面向对象五大原则之依赖倒置原则(DIP)详解
Apr 08 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
ThinkPHP框架中使用Memcached缓存数据的方法
2018/03/31 PHP
Laravel 添加多语言提示信息的方法
2019/09/29 PHP
javascript中callee与caller的用法和应用场景
2010/12/08 Javascript
jquery 模板的应用示例
2013/11/12 Javascript
JavaScript中instanceof与typeof运算符的用法及区别详细解析
2013/11/19 Javascript
jquery ajax jsonp跨域调用实例代码
2013/12/11 Javascript
javascript中clone对象详解
2014/12/03 Javascript
javascript实现点击商品列表checkbox实时统计金额的方法
2015/05/15 Javascript
基于jQuery通过jQuery.form.js插件使用ajax提交form表单
2015/08/17 Javascript
jQuery简单实现input文本框内灰色提示文本效果的方法
2015/12/02 Javascript
JavaScript中boolean类型之三种情景实例代码
2016/11/21 Javascript
巧用Javascript的逻辑运算符
2016/12/02 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
2017/04/28 Javascript
bootstrapTable+ajax加载数据 refresh更新数据
2018/08/31 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
2018/12/10 jQuery
使用uni-app开发微信小程序的实现
2019/12/13 Javascript
Windows下安装 node 的版本控制工具 nvm
2020/02/06 Javascript
python的re模块应用实例
2014/09/26 Python
python 网络爬虫初级实现代码
2016/02/27 Python
python获取list下标及其值的简单方法
2016/09/12 Python
用 Python 连接 MySQL 的几种方式详解
2018/04/04 Python
python判断计算机是否有网络连接的实例
2018/12/15 Python
tensorflow 保存模型和取出中间权重例子
2020/01/24 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
详解python使用金山词霸的翻译功能(调试工具断点的使用)
2021/01/07 Python
Stuart Weitzman欧盟:美国奢华鞋履品牌
2017/05/24 全球购物
英国优质鞋类专家:Robinson’s Shoes
2017/12/08 全球购物
应届生求职推荐信
2013/10/28 职场文书
路政管理毕业自荐书范文
2014/02/10 职场文书
酒店开业庆典主持词
2014/03/21 职场文书
考试作弊被抓检讨书
2014/10/02 职场文书
2015年青年志愿者工作总结
2015/05/20 职场文书
中小学教师继续教育心得体会
2016/01/19 职场文书
2021-4-5课程——SQL Server查询【3】
2021/04/05 SQL Server
CSS3 制作的彩虹按钮样式
2021/04/11 HTML / CSS
vue-cil之axios的二次封装与proxy反向代理使用说明
2022/04/07 Vue.js