谈一下这两个词蕴含的思想。
依赖指一个类或对象A需要在其中依赖别的类或对象B。这样A就依赖于B。
比如
class A{
protect $b;
public function __construct()
{
$this->b = new B();
}
}
这就是说A类依赖B类。
如果依赖关系比较多得话,A的construct中就会比较乱了,而且每增加一个依赖,就需要重写construct。
IoC,控制翻转,即把控制权交给实现者,而不是规则的制定者。规则的制定者只需要提供接口和制定规则,实现着按照一定的规则利用接口将依赖注入到新对象中。
工厂模式就是实现控制翻转的典型例子。由工厂创建者来决定创建的内容,从而不需要每次来新的类型,所有的文件都要改动,
class SuperModuleFactory
{
public function makeModule($moduleName, $options)
{
switch ($moduleName) {
case 'Fight': return new Fight($options[0], $options[1]);
case 'Force': return new Force($options[0]);
case 'Shot': return new Shot($options[0], $options[1], $options[2]);
}
}
}
//只有一个依赖的情况下,用工厂反而更麻烦,好像多次一举
class Superman
{
protected $power;
public function __construct()
{
// 初始化工厂
$factory = new SuperModuleFactory;
// 通过工厂提供的方法制造需要的模块
$this->power = $factory->makeModule('Fight', [9, 100]);
// $this->power = $factory->makeModule('Force', [45]);
// $this->power = $factory->makeModule('Shot', [99, 50, 2]);
/*
$this->power = array(
$factory->makeModule('Force', [45]),
$factory->makeModule('Shot', [99, 50, 2])
);
*/
}
}
//如果多个依赖,则用这种方式就简单多了
class Superman
{
protected $power;
public function __construct(array $modules)
{
// 初始化工厂
$factory = new SuperModuleFactory;
// 通过工厂提供的方法制造需要的模块
foreach ($modules as $moduleName => $moduleOptions) {
$this->power[] = $factory->makeModule($moduleName, $moduleOptions);
}
}
}
// 创建超人
$superman = new Superman([
'Fight' => [9, 100],
'Shot' => [99, 50, 2]
]);
可以看到:我们利用工厂类即factorymodel类中的提供建造工具makemodule方法,然后在创建新产品时,直接用makemodule方法并且传入相应参数即可,而不用亲手一个个依赖new出来。
由于相应参数是在创建产品时传入的,即控制翻转了。
那什么叫依赖注入?
一系列依赖,只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于 依赖注入(DI) 。是不是豁然开朗?事实上,就是这么简单。下面就是一个典型的依赖注入:
// 超能力模组
superModule=newXPower;//初始化一个超人,并注入一个超能力模组依赖
superMan = new Superman($superModule);