依赖注入究竟如何减少耦合?

时间:2010-12-27 21:27:08

标签: dependency-injection

我已经对依赖注入做了很多阅读,但我不知道,它实际上是如何减少耦合的呢?

我对DI的类比是所有组件都在容器中注册,因此它们就像在宝箱中一样。要获得一个组件,你显然首先注册它,但那时你将不得不询问宝箱(这就像一个间接层)。这是正确的比喻吗?然而,“注射”是如何发生的并不明显(如何适应这种类比?)。

由于

4 个答案:

答案 0 :(得分:37)

依赖注入(DI)本身并不减少耦合,因为依赖于依赖关系的组件仍然依赖于它的依赖关系。然而,DI 完成的任务是消除从组件本身找到依赖关系的责任,并将该责任放在其他地方。

依赖于DI的组件在其依赖关系方面是完全被动的。组件中没有代码表示“创建此依赖关系的新实例”或“外出并让我获得此依赖关系”。依赖性是赋予(注入)组件,通常是当组件本身由其他对象创建时。

创建(或要求创建)依赖关系的责任的逆转称为控制反转(IoC)。

因此,如果组件不知道如何创建或要求依赖,那么责任在哪里?通常在专门为依赖项解析创建的对象中,通常称为IoC容器。在你的比喻中,这是你的“宝箱”。 IoC容器包含的说明基本上是“当有人要求这个时,给他们其中一个。一个IoC容器通常可以检查它要创建的组件,图了解它的依赖关系,并创建它们,沿着“依赖链”向下走,直到解决了所有依赖关系。

思考,注入的重大转变来自决定*谁会向容器询问组件的依赖性?“没有DI,组件本身就会要求容器依赖它。但是,使用DI, ,要求容器“解决”组件的依赖性的责任落在创建使用组件的任何东西上。当组件被创建时,创建它的任何东西都有责任提供所有依赖关系。组件不知道或不关心它们是如何创建的,只是它们是。

现在,如果将依赖项定义为具体实现,则该组件仍然紧密耦合到该特定的具体实现,即使它正在被注入。在这种意义上,DI本身不会减少耦合。但是,如果依赖项被定义为接口,则组件不关心或知道具体实现是什么,也不知道它是如何创建的。它仍然依赖于依赖,但它是一个非常松耦合

从这个意义上说,“依赖注入”和“编程到接口”相结合,创建了非常松散耦合,高度灵活的组件。

答案 1 :(得分:4)

将您的组件类比放在宝箱中: 没有依赖注射的系统(比如宝贝抛光机)必须能够从宝箱本身挑选物品。它必须具有依赖性的一些知识才能根据当前的背景选择正确的宝藏。因此耦合。

在DI场景中,您的宝贝抛光机根本不需要了解宝箱的存在。它需要知道的是,在某些时候(最好在创建时),抛光器将被提供(注入)一个实现ITreasure的对象:

interface ITreasure
{
    void PolishMe();
}

因此,您的实施课程将从您的宝箱中解除耦合。

答案 2 :(得分:3)

如果正确使用接口,耦合会特别减少。

如果客户端只知道接口,那么现在可能会打开。您可以自由注入自己的实现或代理版本;你可以在没有客户知情的情况下为方面提供建议;你可以在测试过程中轻松模拟它。如果您只是简单地调用“new”,客户端就不需要知道具体类型。

答案 3 :(得分:1)

在DI中,一个组件仅通过定义良好的接口调用另一个组件,并且所有组件通过配置而不是代码“粘合”在一起。
因此,我们可以通过单独重新配置来交换应用程序使用的实现 作为容器中的示例,您可以将依赖注入可视化为反向查找(如果您已使用JNDI)。 您不需要对资源/模块名称进行硬编码,而是声明类所需的内容(充当bean)。容器负责在运行时提供所有内容。
这个术语是由Martin Fowler创造的,您可以查看他关于概念DI

的文章