依赖注入如何增加耦合?


32

在有关依赖项注入的Wikipedia页面上,劣势部分告诉我们:

依赖注入通过要求子系统的用户满足该子系统的需求来增加耦合。

链接到反对依赖注入的文章

依赖注入使类使用接口而不是具体的实现。那应该导致耦合减少,不是吗?

我想念什么?依赖注入如何增加类之间的耦合?


2
我不确定是谁写了那个缺点列表,但我会一概而论。例如,我已经看到DI通过消除大量冗余设置代码将代码库的大小减少了2/3。
罗布

@RobY我主要使用工厂注入依赖项,而我的经验是,它增加了代码大小,但简化了测试。
BЈовић

尝试使用诸如Registry或Context Passing之类的替代方法;)否则,代码仅实例化对象,然后从config中提取其属性。我主要是在谈论现在和15年前的区别。
罗布(Rob)2014年

相关:stackoverflow.com/a/9503612/264697。马克·西曼(Mark Seemann)的答案解释了如何使用依赖注入减少整体耦合。
2014年

Answers:


42

那么,我想念什么?

依赖注入减少了类与其依赖之间的耦合。但是,它增加了类与其使用者(因为使用者需要更多信息来创建它)和依赖关系及其使用者(因为使用者需要知道要使用的依赖性)之间的耦合。

通常,这是一个很好的权衡。该类不应该了解有关接口以外的依赖项的详细信息,应该由应用程序负责将特定的代码位绑定在一起。


是的,耦合减少了一种方式而增加了另一种方式。
Paul Draper 2014年

但是消费者并没有创造它。这才是重点。
Casey 2014年

@emodendroket-嗯?控制反转使使用者无法创建它。依赖注入与此正交。
Telastyn 2014年

好吧,您是在区分我不熟悉的地方,因为这些术语通常可以互换使用。
Casey 2014年

22

假设您有一个S依赖数据库连接的子系统D。如果没有依赖项注入,则S和之间会有相对紧密的耦合D,因为S需要知道如何使用D和创建它。该系统的其余部分,但是,可以是一无所知之间的这种相关性的SD

依赖注入,之间的耦合S,并D变得更加宽松,因为你从删除S的知识,如何创建一个DS只需要知道如何使用它。整体耦合性的提高是由于系统的其他部分现在需要了解D并且可能需要创建一个。耦合增加的程度取决于对以下项的依赖关系如何D注入S

  • 通过构造函数注入S需求的创建者需要依赖D并且可能需要如何创建依赖的知识。
  • 使用方法级注入S通过其D注入方法的每个调用者都需要依赖D并且可能需要有关如何创建方法的知识。

在这两种情况下,依赖于类的数量都将D增加,并且D需要在系统中的某个位置提供如何创建静态对象的知识。这导致整体上的耦合增加。


好的,这对于构造函数和setter注入是有意义的。但是,如果使用工厂或策略模式,则将创建内容移动到那里,而类仅使用注入的对象。还是那不是依赖注入(仅是控制反转)?
BЈовић

即使使用工厂注入,S需求的创建者也需要提供的工厂D,这意味着它需要知道S使用情况D(或至少它的某些接口)。
Idan Arye 2014年

7

我强烈不同意它会增加耦合。

如果没有依赖项注入,则子系统与依赖项的具体实现之间会紧密耦合。

通过依赖注入,您已经将子系统与依赖的实现分离了。

认为它增加了使用者与该子系统之间的耦合的论点是非常可疑的,因为这意味着使用者现在与子系统所要求的依赖性紧密耦合。这意味着您正在编写紧密耦合的代码,将您的使用者与依赖关系耦合在一起。理想情况下,所有代码都是解耦的。

构造函数注入:

依赖关系解析由依赖关系注入容器或工厂处理。消费者可以从依赖项注入容器或工厂中获得子系统的具体实现。

消费者不需要知道子系统的构造器是什么样子。没有与子系统依赖性的耦合。

方法注入:

与构造函数注入相同,不同之处在于,现在消费者需要从容器或工厂中获取依赖项的具体实例(甚至将其注入方法/构造函数)并将其注入到方法中。再次,消费者没有耦合到依赖的具体实现。

TL; DR 子系统中依赖项注入的最坏情况是将耦合转移到使用者代码。耦合没有整体增加。

最好的情况是,现在所有系统都是松散耦合的,并且依赖注入是通过依赖注入容器或工厂来控制的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.