“控制反转”、“依赖反转”和“解耦”之间的区别

Posted

技术标签:

【中文标题】“控制反转”、“依赖反转”和“解耦”之间的区别【英文标题】:Difference between "Inversion of Control", "Dependency inversion" and "Decoupling" 【发布时间】:2011-04-24 04:09:38 【问题描述】:

我正在阅读关于依赖倒置解耦的理论,我看不出两者之间的区别。

依赖倒置谈到解耦功能组件,以便更高级别的组件不依赖于较低级别的组件。

Decoupling 谈论同样的事情以及如何实现它。但是后来我们有了 IoC 容器,这让事情变得更糟了。为什么不将它们称为 Dependency Inversion Containers 甚至更好的 Dependency Injection Containers,因为它们服务于独立组件的运行时耦合?

然后我们有控制反转。这与依赖倒置基本相同,不是吗?为什么用三个词来描述同一个东西?还是我瞎了?

    这三者有什么区别? IoC 必须在 IoC 容器中做什么?

【问题讨论】:

@Anton Gogolev:解耦用额外的“o”拼写:en.wikipedia.org/wiki/Decoupling#Software_Development 【参考方案1】:

依赖倒置:依赖于抽象,而不是具体。

控制反转:主要与抽象,以及主要如何成为系统的粘合剂。

这些是讨论这个的好帖子:

https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/

https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/

https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/

【讨论】:

【参考方案2】:

我从 martinfowler.com 上的 DIP in the Wild 文章中找到以下解释,易于理解(这里 DI = 依赖注入,DIP = 依赖倒置原则,IoC = 控制反转):

DI 是关于一个对象如何获得依赖关系的。当一个依赖是 外部提供,则系统使用 DI。国际奥委会是关于谁 发起呼叫。如果你的代码发起了一个调用,那不是 IoC,如果 容器/系统/库回调您提供的代码 它,是 IoC。

另一方面,DIP 是关于 从您的代码发送到它正在调用的东西的消息。 (...) DI 是关于 布线,IoC 是关于方向,而 DIP 是关于 [对象的形状 代码所依赖的]。

【讨论】:

“DI 是关于布线,IoC 是关于方向,而 DIP 是关于 [代码所依赖的对象的] 形状。”这是一个很好的句子;) 我发现最后一句话中的shape这个词令人困惑。除了已经说明的内容之外,它似乎没有添加任何内容:DIP 是关于抽象的。我会说 IoC 是关于 ,DIP 是关于 what,DI 是关于 how控制依赖关系? 什么被依赖抽象了? 如何交付依赖项?【参考方案3】:

解耦是一个非常普遍的原则,适用于许多领域。 依赖倒置是一种特殊的解耦形式,您可以通过将系统的较高级别与较低级别分离为库并使用接口来将它们解耦。这使您可以更换系统的较低级别部分,而无需进行重大返工。

例如,可以使用 IoC 容器来解耦对象的创建方式,而不是系统的高级部分创建低级类的具体实例。

控制反转是框架库使用的一种设计原则,它允许框架从应用程序中重新获得一些控制权。即,当某些用户界面事件发生时,窗口框架可能会回调应用程序代码。 Martin Fowler 在不要打电话给我们,我们会打电话给你中使用好莱坞原则这个词。解耦是控制反转的重要组成部分。

但是 IoC 容器 与控制反转有什么关系呢? To quote Martin Fowler:

控制反转是一个过于笼统的术语,因此人们会感到困惑。经过与各种 IoC 倡导者的大量讨论,我们最终确定了 Dependency Injection 这个名称。

(请注意,Martin Fowler 谈论的是依赖注入,而不是依赖倒置。)

IoC 容器有助于实现依赖注入,也许更好的术语是依赖注入容器。但是,IoC 容器名称似乎仍然存在。依赖注入是依赖倒置的一个重要组成部分,但是使用 IoC 容器进行依赖注入可能会令人困惑,因为控制倒置是一个更广泛和更通用的原则。

您指出命名不是很一致,但这并不奇怪,因为这些术语是独立发明和使用的,即使它们重叠。

【讨论】:

我同意,但我不会使用术语 IoC 容器,因为正如您所说,它并不真正正确。我认为在这里遵循(不正确的)流行命名方案并不重要,因为任何了解 DI 容器原理的人都应该能够理解正确的命名。【参考方案4】:

依赖注入使用控制反转实现解耦

【讨论】:

认为控制反转还是虽然依赖反转?我会说是后者。 -1 这实际上将术语“依赖注入”与“控制反转”耦合。依赖注入本身就是一种解耦技术。 @Mauricio:我不认为 依赖注入解耦 或解耦技术。 DI 提供了耦合解耦组件的方法。不是相反。 Hmmm... 依赖注入是一种控制反转的形式,但它不一定能实现很多解耦。依赖倒置是实现解耦的方法,并通过使用依赖注入和控制容器倒置来促进。有用还是更令人困惑? jeez 说得够多了:(鲍里斯写得很好。有太多的方法可以做任何事情。重要的是团队内部的信任和尊重。从最纯粹的角度来看,有'如果团队合作是最佳的并且存在对自己工作的信念,那么软件设计原则和有关它们的书籍就没有用处。

以上是关于“控制反转”、“依赖反转”和“解耦”之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之美——依赖反转原则

浅谈“面向接口编程” :依赖反转 IOC 与 DI (容器控制反转与依赖注入)

SpringIoc依赖注入依赖反转

依赖反转Ioc和unity,autofac,castle框架教程及比较

IOC和DI的区别详解

SpringIoC:控制反转 总结