为什么要传递对象而不是在依赖注入中创建它们?

时间:2017-09-03 09:31:48

标签: symfony dependency-injection mocking

DI中的基本概念是应该传递依赖对象,而不是在依赖对象中创建它们。

我能找到的原因只有this answer

  1. 隐藏依赖关系的构造细节,使代码不那么难看。
  2. 为了便于单元测试中的模拟。
  3. 还有其他原因吗?

    如果没有,你能否解释一下这些理由,以证明DI的合理性?

2 个答案:

答案 0 :(得分:4)

让我们看一下现实生活中的例子。假设你有一辆车。汽车需要一台发动机。

class Car
{
    private $engine;

    public function __construct()
    {
        $this->engine = new V6Engine();
    }
}

汽车依赖发动机。在这种情况下,汽车本身需要构建一个新的引擎! 是否有意义? 嗯..不! 此外,汽车与特定版本的发动机相连。

这更有意义。 其他人需要提供汽车引擎。它可能是一些发动机供应商,发动机工厂......创造发动机不是汽车的工作!

class Car
{
    private $engine;

    public function __construct(Engine $engine)
    {
        $this->engine = new $engine;
    }
}


interface Engine
{
    public function start();
}

class V6Engine implements Engine
{
    public function start()
    {
        echo "vrooom, vrooom V6 cool noise"
    }
}

此外,您可以轻松更换引擎,而不是特定引擎。新引擎只需要能够启动。

Martin Fowler撰写了一篇关于控制和依赖注入反转的非常好的文章。

https://martinfowler.com/articles/injection.html

请阅读 - 因为他会比我能做的更好地解释DI :)))

另外,MiškoHevery有“非常好的视频”“清洁代码会谈 - 不要寻找东西!”。看完之后你会非常聪明:)

https://www.youtube.com/watch?v=RlfLCWKxHJ0

答案 1 :(得分:2)

我想补充一点,在服务中创建对象会隐藏服务范围。

要求它作为一个硬依赖使得它明确表明你的服务需要一个这样的对象的实例才能工作。通过使其成为合同的一部分,依赖性不再是实现细节。

这也是为了灵活性而打开,你可以打字,例如EngineInterface而不是具体的实现,这意味着你不关心什么实现传递给你的服务,而是依赖于接口强加的合同(想象一个邮件发送邮件用于生产,但是没有操作用于测试)。