码迷,mamicode.com
首页 > 其他好文 > 详细

控制反转与依赖注入

时间:2015-06-21 19:48:59      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

依赖注入是php编程中的一种设计模式,其目的也是为了降低耦合度,提高可维护性。

问题现象:
我们在编程过程中常常遇到一个类中实例化另外一个类,这个类中又实例化了一个其他类,这种层层包裹的形式,常常使我们在修改代码的时候,修改了一次,相关的上层也要跟着修改,如果层级关系比较复杂,这种修改就是灾难性的。
解决办法:
为了解决上述的问题,有人就提出了一种构想,可不可以让上层只定义接口,而由下层来实现接口,这样就变成了下层依赖上层,这种构想被称为依赖倒置原则(DIP),这种策略会降低耦合度,提高可用性,实现这种构想的方法之一就是控制反转(IOC),简单的讲控制反转的思路就是类对于自己所依赖的类,不在本类中做实例化,全部交由第三方来实例化,然后通过属性或者类构造函数来把是实例传递进本来,这个方式就是依赖注入(DI),这个第三方就是控制反转容器,如果这个第三方是Service Loader那么这个就被称为服务定位器,这个也是控制反转的实现方式。
总结:
依赖注入是控制反转的具体方法之一,这种方法是为了实现依赖倒置原则,解决上层类对于下层类的依赖耦合,提高可用性。
说明:
在php的各种框架中,都会为了依赖注入提供第三方的类来实现控制反转容器,方便编程。以下例子以YII2.0.4框架为例。
举例:
// 为Excel定义一个接口类
interface ExcelInterface
{
public function OutExcel(...);
}
 
// 定义Excel文件生成类
class ExcelFile implements ExcelInterface
{
 
// 实现生成excel文件的方法
public function OutExcel(){}
}
 
// 这是库存AR类
class Stock extend yii\db\ActiveRecord
{
private $_excelExt;
 
// 将$_excelExt赋值为ExcelFile的实例
public function init()
{
$this->_excelExt = new ExcelFile()
}
 
// 当需要的时候调用excelfile类
public function doSomething()
{
$this->_excelExt->OutExcel();
}
}
现在这里有两个问题
1,如果你修改了ExcelFile类,修改了相关的方法名,参数,返回等等,那么相应的Stock类也需要做修改,而且无论谁调用了Stock类中的dosomething,都会受影响,然后再下一层呢?这样改下去是不是灾难性的?
2,如果有一天你不想输出为excel,或者说你想让excel和pdf格式都受支持,除了小心翼翼的修改dosomething以及其上层调用方法外,有没有其他办法呢?
方法就是依赖注入,Stock所用到的类是除了ExcelFile外的第三方传递给它的,它只是拿来用,修改操作都在第三方完成,和Stock没有关系,传递的方法有两种,属性传递或者构造函数传递,这里的传递你也可以称为注入
// 属性注入
class Stock extend yii\db\ActiveRecord
{
private $_excelExt;
 
// 为了方便类实例的注入,这里定义了Set方法,在yii里这里会转化为Set魔术方法
public function setEmailSender($value)
{
$this->_excelExt = $value;
}
 
// 当需要的时候调用excelfile类
public function doSomething()
{
$this->_excelExt->OutExcel();
}
}
 
 
$Exceler = new ExcelFile();
$Pdfer = new PdfFile();
 
$comment1 = new Stock;
// 使用属性注入
$comment1->excelExt = $Exceler;
// 生成excel文件
$comment1->doSomething();
 
$comment2 = new Stock;
// 使用属性注入
$comment2->excelExt = $Pdfer;
// 生成pdf文件
$comment1->doSomething();
 
 
 
// 这是构造函数注入的例子
class Stock extend yii\db\ActiveRecord
{
private $_excelExt;
 
// 构造函数注入
public function __construct($filer)
{
$this->_excelExt = $filer;
}
 
// 当需要的时候调用excelfile类
public function afterInsert()
{
$this->_excelExt->OutExcel();
}
}
 
 
 
$Exceler = new ExcelFile();
$Pdfer = new PdfFile();
 
// 用构造函数注入
$comment1 = new Comment($Exceler);
 
// 用构造函数r注入
$comment2 = new Comment($Pdfer);
 
 
 
这里通过注入的方式解耦了类关联,所有依赖类的实例化都放在类外实现,这就是依赖注入的本质,在yii中有一个专门提供的类用来实例化依赖,被称为DI容器,依赖注入容器
 
use yii\di\Container;
 
// 创建一个DI容器
$container = new Container;
 
// 为UserLister定义一个别名
$container->set(‘excel‘, ‘app\ExcelFile‘);
 
// 获取这个UserList的实例
$lister = $container->get(‘excel‘);

 

控制反转与依赖注入

标签:

原文地址:http://www.cnblogs.com/phpinfo/p/4592252.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!