php中这两种类型的构造函数注入有什么区别?

时间:2015-09-29 06:44:32

标签: php laravel dependency-injection type-hinting

我正在尝试理解PHP中的依赖注入,我发现在Laravel中有两种方法可以做到这一点。

所以,让我们说我有一个类Foo,如此:

class Foo{

}

现在我有一个名为Bar的课程,它依赖于Foo,所以我可以这样做:

class Bar{
    protected $foo;
    public function __construct()
    {
        $this->foo = new Foo();
    }
}

但是在Laravel中,我遇到了类似写法和反射这样的术语,这些术语允许我这样做:

class Bar{
    protected $foo;
    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
    }
}

我想要了解的是这两者之间的区别。它们完全相同吗?是否有一个我应该优先考虑的具体原因?

PS:我是新手,我不确定我是否正确使用了问题中的行话。

1 个答案:

答案 0 :(得分:1)

主要归结为代码的耦合

class Foo {
    public function __construct() {
        new Bar;
    }
}

这会将非常具体的Bar与此特定Foo结合起来。在没有重写此代码的情况下,无法更改哪个 Bar被实例化。这也意味着Foo需要了解Bar的依赖关系。也许今天Bar只能使用new Bar进行实例化。但也许明天你要重构Bar,现在必须用new Bar($database)实例化它。现在,您还需要重写Foo以适应这种情况。

这就是依赖注入的来源(上面是不是依赖注入,你不是注入任何东西):

class Foo {
    public function __construct(Bar $bar) { }
}

这个Foo只是在实例化时声明它需要一个具有Bar特征的对象。但是Foo不需要知道Bar是如何形成的,它的依赖关系是什么或它究竟是什么。它对Bar唯一期望的是定义的public接口,关于它的任何其他内容都无关紧要。实际上,为了获得更大的灵活性,您可能希望在此使用interface而不是具体的类依赖。

依赖注入允许您将类的具体细节与其他代码分开。它允许您有一个实例化类的中心位置,这是您需要知道并考虑有关您实例化的类的具体细节的地方。例如,这可以是依赖注入容器。您不希望在整个地方传播类实例化逻辑,因为如上所述,该逻辑可能会发生变化,然后您需要在整个地方重写代码。

require_once 'Foo.php';
require_once 'Bar.php';

$foo = new Foo(new Bar);

以上代码是 Bar注入Foo的地方。它也是需要担心Bar依赖关系的地方。请注意,依赖性加载和实例化是此代码唯一的功能。根据需要仅更改这段代码是微不足道的,无需触及FooBar,这可能充满了复杂的业务逻辑。

依赖注入代码还允许您将应用程序拆分并灵活地组合在一起。例如,用于测试目的。或者只是在不同的环境中灵活地重用不同的组件。

另见How Not To Kill Your Testability Using Statics