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 批量删除 sql语句
Jun 05 PHP
PHP 命名空间实例说明
Jan 27 PHP
新浪微博API开发简介之用户授权(PHP基础篇)
Sep 25 PHP
PHP判断一个gif图片是否为动态图片的方法
Nov 19 PHP
PHP针对字符串开头和结尾的判断方法
Jul 11 PHP
php封装的验证码工具类完整实例
Oct 19 PHP
PHP laravel中的多对多关系实例详解
Jun 07 PHP
由php中字符offset特征造成的绕过漏洞详解
Jul 07 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
Dec 21 PHP
php使用scandir()函数扫描指定目录下所有文件示例
Jun 08 PHP
php链式操作的实现方式分析
Aug 12 PHP
PHP使用PhpSpreadsheet操作Excel实例详解
Mar 26 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
用cookies来跟踪识别用户
2006/10/09 PHP
win7系统配置php+Apache+mysql环境的方法
2015/08/21 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
PHP执行普通shell命令流程解析
2020/08/24 PHP
Javascript中暂停功能的实现代码
2007/03/04 Javascript
javascript结合canvas实现图片旋转效果
2015/05/03 Javascript
BootStrap中Table分页插件使用详解
2016/10/09 Javascript
Node连接mysql数据库方法介绍
2017/02/07 Javascript
Vue2单一事件管理组件通信
2017/05/09 Javascript
JS中精巧的自动柯里化实现方法
2017/12/12 Javascript
浅谈使用React.setState需要注意的三点
2017/12/18 Javascript
jQuery 实现左右两侧菜单添加、移除功能
2018/01/02 jQuery
JavaScript实现图片懒加载的方法分析
2018/07/05 Javascript
vue点击input弹出带搜索键盘并监听该元素的方法
2018/08/25 Javascript
详解Vue CLI 3.0脚手架如何mock数据
2018/11/23 Javascript
JS操作json对象key、value的常用方法分析
2019/10/29 Javascript
ES6学习笔记之let与const用法实例分析
2020/01/22 Javascript
Python的ORM框架SQLObject入门实例
2014/04/28 Python
python模拟鼠标拖动操作的方法
2015/03/11 Python
python中函数默认值使用注意点详解
2016/06/01 Python
Python实现抓取网页生成Excel文件的方法示例
2017/08/05 Python
python3 读写文件换行符的方法
2018/04/09 Python
python方法生成txt标签文件的实例代码
2018/05/10 Python
python basemap 画出经纬度并标定的实例
2019/07/09 Python
Python 获取 datax 执行结果保存到数据库的方法
2019/07/11 Python
Keras SGD 随机梯度下降优化器参数设置方式
2020/06/19 Python
用C#语言写出与SQLSERVER访问时的具体过程
2013/04/16 面试题
一个大学生十年的职业规划
2014/01/17 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
自主招生学校推荐信
2014/09/26 职场文书
2014最新自愿离婚协议书范本
2014/11/19 职场文书
2015年消防工作总结
2015/04/24 职场文书
工作态度怎么写
2015/06/25 职场文书
2019 入党申请书范文
2019/07/10 职场文书
MySQL COUNT函数的使用与优化
2021/05/10 MySQL
Java9新特性之Module模块化编程示例演绎
2022/03/16 Java/Android