依赖注入

推荐一篇介绍依赖注入的基础文章依赖注入基础讲解

说白了, 依赖注入就是不直接在使用类的内部创建对象, 而是将对象作为调用类的一个属性, 这样能够降低类与类之间的耦合, 使程序更加的灵活可变。还是举个简单的例子吧。

先来定义三个文件分别是 IGun.php , PistolGun.php, Soldier.php

//IGun.php
interface IGun
{
    public function getName();

    public function shoot();

}

// PistoGun.php
class PistolGun implements IGun
{
    private $name = 'Pisto';

    public function getName()
    {
        return $this->name;
    }

    public function shoot()
    {
        echo 'Pisto shoot' . PHP_EOL;
    }
}

// Soldier.php
// 士兵使用枪射杀敌人
class Soldier
{
    private $gun;

    public function __construct()
    {
        $this->gun = new PistolGun();
    }

    public function shoot()
    {
        echo 'soldier use ' . $this->gun->shoot();
    }

    public function getGunName()
    {
        echo $this->gun->getName();
    }
}

这样的代码应该是很容易写出来的, 现在问题来了, 为了增强士兵的杀敌能力和自保能力, 政府决定每人一把加特林。为了更改我们必须修改这个类,但是在下一次战争中可能是游击战, 为了灵活又要使用手枪了, 这种事情虽然不可能出现, 但在编程世界里应该随时都可能发生, 为了能够使这个类更加灵活, 于是就引入了依赖注入一说, 现在我们增加一个类, 并且使用依赖注入的写法。

// Gatling.php
class Gatling implements IGun
{
    private $name = 'Gatling';
    public function shoot()
    {
        echo $this->name . 'shoot' . PHP_EOL;
    }

    public function getName()
    {
        return $this->name;
    }
}

// 依赖注入的写法

// Soldier.php
// 士兵使用枪射杀敌人
class Soldier
{
    private $gun;

    public function __construct(IGun $_gun)
    {
        $this->gun = $_gun;
    }

    public function shoot()
    {
        echo 'soldier use ' . $this->gun->shoot();
    }

    public function getGunName()
    {
        echo $this->gun->getName();
    }

}

(new Soldier(new Gatling())) -> shoot();  //使用加特林的士兵射击
(new Soldier(new PistolGun())) -> shoot();  // 使用手枪的士兵射击

依赖注入就是通过注入不同的对象来实现灵活性, 但是我们需要使用约束(接口和抽象)以保证程序的正常运行(总不能随便一个类我就用吧) 除了通过构造函数,也可以使用setter方法注入依赖。

// 在Solder中
public function setGun(IGun $_gun) {
    $this->gun = $_gun;
}

如果使用setter方法, 或许需要加点检测, 以防止没有调用setter方法, 就开始上阵杀敌。试想下, 你上战场了, 但是忘了带枪了(这样我想起了一部电影–血战钢锯岭, 但我觉得不是每个人都有那样的运气。)这基本和故意送人头没区别了, 是要被举报的。