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

Roh*_*han 7 php dependency-injection type-hinting laravel

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

那么让我们说我有一个Foo这样的课程:

class Foo{

}
Run Code Online (Sandbox Code Playgroud)

现在我有一个被称为Bar依赖的类,Foo所以我可以这样做:

class Bar{
    protected $foo;
    public function __construct()
    {
        $this->foo = new Foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

class Bar{
    protected $foo;
    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要了解的是这两者之间的区别.它们完全相同吗?是否有一个特别的原因我应该优先于另一个?

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

dec*_*eze 1

这主要归结为代码的耦合

class Foo {
    public function __construct() {
        new Bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

Bar与一个非常具体的具体结合起来Foo。如果不重写此代码,则无法更改实例化的内容 Bar。这也意味着Foo需要了解 的Bar依赖关系。也许今天Bar可以用 来实例化new Bar。但也许明天您要重构Bar并且现在必须使用 实例化它new Bar($database)。现在您还需要重写Foo以适应这一点。

这就是依赖注入的用武之地(上面不是依赖注入,你没有注入任何东西):

class Foo {
    public function __construct(Bar $bar) { }
}
Run Code Online (Sandbox Code Playgroud)

Foo只是声明它需要一个具有实例化特征的对象Bar。但Foo不需要知道任何关于它是如何Bar发生的、它的依赖项是什么或者它到底做什么的事情。它唯一期望的Bar是一个已定义的public接口,其他任何内容都是无关紧要的。事实上,为了获得更大的灵活性,您可能需要interface在此处使用而不是具体的类依赖项。

依赖注入允许您将类的具体细节与其他代码分开。它允许您拥有一个实例化类的中心位置,在该位置您需要了解并考虑有关正在实例化的类的具体细节。例如,这可以是依赖项注入容器。您不想将类实例化逻辑散布到各处,因为如上所述,该逻辑可能会发生变化,然后您需要到处重写代码。

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

$foo = new Foo(new Bar);
Run Code Online (Sandbox Code Playgroud)

上面的代码是决定将哪个 Bar注入到Foo. Bar这也是需要担心依赖关系的地方。请注意,依赖项加载和实例化是此代码所做的唯一事情。根据需要只更改这段代码是很简单的,而不需要接触FooBar,这可能充满了复杂的业务逻辑。

依赖注入的代码还允许您将应用程序分开并灵活地将其组合在一起。例如用于测试目的。或者只是为了在不同的上下文中灵活地重用不同的组件。

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