我正在尝试理解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:我是新手,我不确定我是否正确使用了问题中的行话。
答案 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
依赖关系的地方。请注意,依赖性加载和实例化是此代码唯一的功能。根据需要仅更改这段代码是微不足道的,无需触及Foo
或Bar
,这可能充满了复杂的业务逻辑。
依赖注入代码还允许您将应用程序拆分并灵活地组合在一起。例如,用于测试目的。或者只是在不同的环境中灵活地重用不同的组件。