在2011年10月份左右,在symfony和zf1的框架中有一个重要的版本更新,那就是加入了DICs(Dependency Injection Containers),并把DICs作为创建对象的首要思想,而ZF2重写了DICs的思想,并封装成了DI模块,位于“Zend\Di”
那么究竟什么是DI(依赖注入)呢?
简单来说,DI是一个设计模式,以前叫IOC(Inversion of Control),它代表了所依赖的对象的内部实现,你不用再为了实现一个功能,在一个类的内部创建set、get、__construct、public vars等来实现外部类的调用,所有的这些我们都可以通过定义接口来实现
听着是不是有些耳熟?这是因为其实DI是一种常见的设计模式,你如果有经常使用php的单元测试工具“phpunit”,那么你肯定对依赖注入的概念有个直观的了解
假设我们有一个类叫做Robot(机器人),那么机器人离不开什么呢?对了,是电池!所以我们就有了一个依赖的对象Battery(电池),我们很容易的就可以创建一个Robot类,只需要在类内部调用Battery即可
如果你这样实现,会有什么问题呢?其实当然没有问题了,一切运行OK,但是如果后来我们支持国产,只能使用中国的电池(BatteryOfChina)?同时我们需要在单元测试(phpunit)中复制一个Battery作为测试用例?而这个时候其他人员发现了Battery中存在一个bug,我们需要修复这个bug,但是我们不能或者不想修改源代码(代价很高)?请问上面的设计还能解决这些问题吗?显然答案是否定的
所有这些问题的解决方案是什么呢?那就是通过第三方的依赖注入来代替内部创建,根据我们上面的假设,我们可以定义一个基础方法setBattery(),来接受任何来自于接口Battery的实现(implement),为什么使用接口而不是类?因为我们希望不管是中国电池还是美国电池,都能遵循统一的标准,具有基本的功能(充电、放电等)
我们来看下原来的代码实现
我们来看下DI的实现方式:
看出其中的奥妙了吗?其实DI真正实现了按需索取,而不是照本宣科,需要的时候相关的类才会被实例化,而不是事先把所有需要的类都实例化,延迟加载的思路和这个是差不多的其实,这其实就是DI的核心所在:通过抽象出对象的接口来实现依赖关系的反转。 DI的这种实现方式恰好就是状态(State)模式的完整体现,我们例子中得ChinaBattery和OtherBattery就是两种不同的状态,利用抽象接口实现不同的状态间的相互切换,便于功能扩展和耦合度的减轻。 在ZF2中模块中Controller就是Robot的作用,在controller里面我们进行一系列的操作来实现我们需要的功能,cotroller会自动为我们加载实现这些功能所依赖的类,然后注入到自己的实现方法里面来
转自http://helion.name/archives/489.html