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 cookie 作用范围?不要在当前页面使用你的cookie
Mar 24 PHP
PHP 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
Jul 17 PHP
使用Apache的htaccess防止图片被盗链的解决方法
Apr 27 PHP
基于php无限分类的深入理解
Jun 02 PHP
php实现refresh刷新页面批量导入数据的方法
Dec 23 PHP
php实现将wav文件转换成图像文件并在页面中显示的方法
Apr 21 PHP
PHP简单生成缩略图相册的方法
Jul 29 PHP
WordPress中用于获取文章作者与分类信息的方法整理
Dec 17 PHP
thinkphp中字符截取函数msubstr()用法分析
Jan 09 PHP
浅谈PHP面向对象之访问者模式+组合模式
May 22 PHP
PHP框架实现WebSocket在线聊天通讯系统
Nov 21 PHP
PHP设计模式概论【概念、分类、原则等】
May 01 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实现自动获取生成文章主题关键词功能的深入分析
2013/06/03 PHP
国产PHP开发框架myqee新手快速入门教程
2014/07/14 PHP
学习php设计模式 php实现装饰器模式(decorator)
2015/12/07 PHP
PHP数据库连接mysql与mysqli对比分析
2016/01/04 PHP
Thinkphp框架中D方法与M方法的区别
2016/12/23 PHP
thinkPHP5框架实现基于ajax的分页功能示例
2018/06/12 PHP
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
jQuery TextBox自动完成条
2009/07/22 Javascript
JavaScript栏目列表隐藏/显示简单实现
2013/04/03 Javascript
js实现jquery的offset()方法实例
2015/01/10 Javascript
详解JavaScript中双等号引起的隐性类型转换
2016/05/30 Javascript
Vue表单实例代码
2016/09/05 Javascript
VsCode插件整理(小结)
2017/09/14 Javascript
jquery学习笔记之无new构建详解
2017/12/07 jQuery
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
2019/11/01 Javascript
vue-cli点击实现全屏功能
2020/03/07 Javascript
详解datagrid使用方法(重要)
2020/11/06 Javascript
Python实现mysql数据库更新表数据接口的功能
2017/11/19 Python
django框架CSRF防护原理与用法分析
2019/07/22 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
关于python 的legend图例,参数使用说明
2020/04/17 Python
django中cookiecutter的使用教程
2020/12/03 Python
Python实现区域填充的示例代码
2021/02/03 Python
英国排名第一的餐具品牌:Denby Pottery
2019/11/01 全球购物
俄罗斯三星品牌商店:GalaxyStore
2020/11/04 全球购物
新大陆软件面试题
2016/11/24 面试题
会计专业应届生求职信
2013/11/24 职场文书
工伤事故赔偿协议书
2014/04/15 职场文书
2014年技术工作总结范文
2014/11/20 职场文书
2014七年级班主任工作总结
2014/12/05 职场文书
2015年社区综治工作总结
2015/04/21 职场文书
2015年试用期工作总结范文
2015/05/28 职场文书
子女赡养老人协议书
2016/03/23 职场文书
深入理解以DEBUG方式线程的底层运行原理
2021/06/21 Java/Android
Oracle安装TNS_ADMIN环境变量设置参考
2021/11/01 Oracle
MySQL批量更新不同表中的数据
2022/05/11 MySQL