【问题标题】:What is the difference between these two types of constructor injections in php?php中这两种构造函数注入有什么区别?
【发布时间】:2015-12-26 13:00:57
【问题描述】:

我正在尝试理解 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:我是新手,我不确定我是否正确使用了问题中的行话。

【问题讨论】:

  • 第一个例子很难测试,因为你不能在 Bar 中模拟 Foo;第二个称为依赖注入 (DI),它允许您在测试 Bar 时模拟 Foo
  • What is dependency injection? 的可能重复项
  • 第二个也消除了 Foo 实际上是 Foo 实例的必要性,但允许它是 Foo 或任何扩展 Foo 的类的实例(类型提示强制执行)... . 松耦合,因为你不再受限于实际的 Foo
  • @MarkBaker:所以你的意思是说,如果我编写一个接口并且它有多个实现,控制器不需要知道我要使用哪个实现,我可以输入提示界面。我理解对了吗?
  • 您理解正确:您不需要 DI 的类型提示;但是提示松散耦合的接口是 typehint 的价值.... DI 本身对于使类更易于测试很有价值,但不需要 typehint;但这也是通过类型提示进行松散耦合的必要步骤

标签: php laravel dependency-injection type-hinting


【解决方案1】:

这主要归结为代码的耦合

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

这会将一个非常具体的Bar 与这个具体的Foo 结合起来。没有办法改变 which 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,可能充满了复杂的业务逻辑。

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

另见How Not To Kill Your Testability Using Statics

【讨论】:

  • 非常感谢您的详细回答。我很感激。 :)
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
相关资源
最近更新 更多