依赖注入(Dependency Injection,DI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象。
所谓的依赖就是,一个对象,要使用另外一个对象才能完成某些功能。那么这个对象就依赖于被使用的对象。
例如:
/** * 厨师 */ class cook { /** * 制作食物 */ public function cooking() { $food = new food(); echo $food->get(),"汤<br/>"; } } /** * 食材 */ class food{ /** * 提供食材 */ public function get() { return '西红柿鸡蛋'; } }
厨师类 在 制作食物 的时候需要用到 食材类 提供食材,才能完成食物的制作。
所以厨师类依赖于食材类。
但是这种直接在类内部实例化一个对象的方式来得到对象,是一种强耦合的做法。
应该把食材的提供者(数据结构)与食物的制作方法(算法)进行分离。
再改动一下代码:
/** * 厨师 */ class cook { private $food; public function __construct(food $food) { $this->food = $food; } /** * 制作食物 */ public function cooking() { echo $this->food->get(),"汤<br/>"; } } /** * 食材 */ class food{ /** * 提供食材 */ public function get() { return '西红柿鸡蛋'; } }
改动之后的代码是在实例化一个厨师的时候就把食材类传递进去。
但是这个时候,如果改动了,food类,那么极有可能导致cook类不能得到食材。这个时候它们之间还是强耦合在一块。
况且厨师不可能总是做西红柿鸡蛋汤啊,他需要其它食材。
再改动一下代码:
/** * 厨师 */ class cook { private $food; public function __construct(food $food) { $this->food = $food; } /** * 制作食物 */ public function cooking() { echo $this->food->get(),"汤<br/>"; } } /** * 食材接口 */ interface food{ public function get(); } /** * 海鲜类食材 */ class seafood implements food{ /** * 提供食材 */ public function get() { return '鲜鱼'; } } /** * 家禽类食材 */ class fowlfood implements food{ /** * 提供食材 */ public function get() { return '西红柿鸡蛋'; } }
把 食材提供 用一个接口进行约定,然后各类食材都必须实现那个接口。
通过接口,把 cook 与 food 彻底分开。
这样我们的客户端代码就是:
$cook = new cook(new seafood); $cook->cooking(); $cook = new cook(new fowlfood); $cook->cooking();
这样在每次使用$cook对象的时候,都需要new一下 实现了food接口的类。
那么对于这种依赖的关系,如果能够让一个对象专门来处理,而不是手工去new一下food类。那么这种处理过程就叫依赖注入。
这个处理依赖关系的对象就是Yii框架中的叫“”容器”的对象。
下面是Yii中依赖注入容器的使用:
<?php namespace appcontrollers; use yiiwebController; use YII; class TestController extends Controller { public function actionIndex() { //实例化依赖注入容器 $container = new yiidiContainer; //设置food接口与具体的实现类之间的关系 $container->set('appcontrollersfood','appcontrollersfowlfood'); //$container->set('appcontrollersfood','appcontrollersseafood'); //通过依赖注入容器得到厨师对象 $cook = $container->get('appcontrollerscook'); $cook->cooking(); } } /** * 厨师 */ class cook { private $food; public function __construct(food $food) { $this->food = $food; } /** * 制作食物 */ public function cooking() { echo $this->food->get(),"汤<br/>"; } } /** * 食材接口 */ interface food{ public function get(); } /** * 海鲜类食材 */ class seafood implements food{ /** * 提供食材 */ public function get() { return '鲜鱼'; } } /** * 家禽类食材 */ class fowlfood implements food{ /** * 提供食材 */ public function get() { return '西红柿鸡蛋'; } }