我正在尝试理解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
的依赖关系的地方。注意,依赖项加载和实例化是这段代码唯一要做的事情。在必要时只更改这段代码是很简单的,不需要触及Foo
或Bar
,它们可能充满了复杂的业务逻辑。
依赖注入代码还允许你把应用拆开,然后灵活地组合在一起。例如用于测试目的。或者只是在不同的上下文中灵活地重用不同的组件。
请参见如何不使用静态静态来破坏您的可测试性