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


What is the difference between these two types of constructor injections in php?

我正在尝试理解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;
    }
}

我想了解的是这两者之间的区别。它们完全相同吗?有什么特别的原因让我更喜欢on而不是其他吗?

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

这主要归结为耦合代码。

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,它们可能充满了复杂的业务逻辑。

依赖注入代码还允许你把应用拆开,然后灵活地组合在一起。例如用于测试目的。或者只是在不同的上下文中灵活地重用不同的组件。

请参见如何不使用静态静态来破坏您的可测试性