简单的例子理解依赖注入(PHP)
最近在学习laravel框架,其中多次提到依赖注。之前对依赖注入只有一个模糊的概念,并没有明确的认识,打算借这次机会深入学习一下。
我的理解 依赖注入就是依赖类不应该自己实例被依赖的类,应该将实例化被依赖类的工作交给外部容器来进行。
主要的 目的就是实现 控制反转,而控制反转的目的就是 解耦。
而解耦的目的就是使代码”面向需求“、”拥抱变化“。
我们用一个例子来理解,
我们设定一个简单的前提:成为士兵(soldier)有一个条件,就是要拥有一把剑(sword)。
我们抽象成代码:
紧耦合的情况
基本情况
剑的类:
class Sword
{
public function useSword()
{
echo '冲啊~~~!<br/>';
}
}
士兵的类:
class Soldier
{
//士兵的武器
public $sword;
public function __construct()
{
$this->sword = new Sword();
}
//战斗
public function fight()
{
//挥舞剑
$this->sword->useSword();
}
}
当士兵应征的时候:
//征兵
$soldier1 = new Soldier();
$soldier2 = new Soldier();
//上战场
$soldier1->fight();
$soldier2->fight();
被依赖的类发生变更时
当剑(sword)的结构发生变更时,比如说添加了一个属性长度(length)而且我们需要在实例化剑(sword)的时候给出长度(length)时,我们不但要修改Sword类的代码,也要修改Soldier类的代码。
如下代码:
剑的类:
class Sword
{
//剑的长度
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function useSword()
{
echo '冲啊~~~!<br/>';
}
}
士兵的类:
class Soldier
{
//士兵的武器
public $sword;
public function __construct($length)
{
$this->sword = new Sword($length);
}
//战斗
public function fight()
{
//挥舞剑
$this->sword->useSword();
}
}
当士兵应征的时候:
//征兵
$soldier1 = new Soldier(20);
$soldier2 = new Soldier(100);
//上战场
$soldier1->fight();
$soldier2->fight();
所以说,每一次我们带边剑(Sword)的结构(比如说添加材质属性,添加制作工艺)都会影响到士兵(Soldier)。
依赖注入的情况下
但是在使用 依赖注入的情况下,就会不会发生这样的情况:
剑的类:
class Sword
{
public function useSword()
{
echo '冲啊~~~!<br/>';
}
}
士兵的类:
class Soldier
{
//士兵的武器
public $sword;
public function __construct(Sword $sword)
{
$this->sword = $sword;
}
//战斗
public function fight()
{
//挥舞剑
$this->sword->useSword();
}
}
当士兵应征的时候:
//制作剑
$sword1 = new Sword(20);
$sword2 = new Sword(100);
//征兵
$soldier1 = new Soldier($sword1);
$soldier2 = new Soldier($sword2);
//上战场
$soldier1->fight();
$soldier2->fight();
我们可以看到剑(Sword)是我们在外部实例化之后注入给士兵(Soldier)的,他们之间被完全解耦了,无论剑的需求发生什么样的扩展(变更),只要可以战斗(useSword)都不会影响士兵。
这样就达到了’拥抱变化’的目的,同时也更方便测试。