【发布时间】:2015-03-14 18:08:17
【问题描述】:
我正在学习春天。我理解依赖注入。在某些地方,我还看到它称为依赖倒置。我知道为什么它被称为注入,但“反转”是什么意思?它实际上反转了哪个依赖项?
【问题讨论】:
-
本质上,Spring将依赖管理从Application倒置到Container(Spring Container)。这就是依赖倒置出现的地方。
我正在学习春天。我理解依赖注入。在某些地方,我还看到它称为依赖倒置。我知道为什么它被称为注入,但“反转”是什么意思?它实际上反转了哪个依赖项?
【问题讨论】:
好问题 - inversion 这个词有点令人惊讶(因为在应用 DIP 之后,较低级别的依赖模块现在显然不会在较高级别的调用者模块上使用 depend - 调用者和依赖现在只是通过额外的抽象更松散地耦合)。
引用 Robert C Martin 的 original source
有人可能会质疑我为什么使用“反转”这个词。坦率地说,这是因为更传统的软件开发方法,例如结构化分析和设计,倾向于创建高级模块依赖于低级模块,抽象依赖于细节的软件结构。实际上,这些方法的目标之一是定义描述高级模块如何调用低级模块的子程序层次结构。 ...因此,设计良好的面向对象程序的依赖结构相对于通常由传统过程方法产生的依赖结构是“倒置的”。
阅读 Bob 大叔关于 DIP 的论文时要注意的一点是,C++(和at time of writing, still doesn't)没有接口,因此在 C++ 中实现这种抽象通常是通过抽象/纯虚拟基类实现的,而在Java 或 C# 放松耦合的抽象通常是通过从依赖项中抽象出接口,并将更高级别的模块耦合到接口来解耦。
编辑 澄清一下:
“在某些地方我也看到它被称为依赖倒置”
请注意,Dependency Injection (DI) 是实现依赖倒置原则 (DIP) 的可能实现之一 - the "D" in SOLID design principles,因此 DI 和 DIP 是不完全可互换的。 p>
其他 DIP 实现包括 Service locator pattern(现在是 often regarded 作为反模式);和Plugin。
【讨论】:
反转: 反转从应用到容器的依赖管理(例如 Spring)。
依赖注入:
与其编写工厂模式,不如将对象直接注入到客户类中。所以让客户类引用接口,我们应该能够将具体类型注入客户类。这样,客户类就不需要使用 new 关键字,并且与具体类完全解耦。
那么控制反转 (IoC) 是什么?
在传统编程中,业务逻辑的流程由静态分配给彼此的对象确定。使用控制反转,流程依赖于由组装器实例化的对象图,并且通过抽象定义的对象交互使之成为可能. 绑定过程是通过依赖注入实现的,尽管有些人认为使用服务定位器也提供了控制反转。
控制反转作为设计指南的目的如下:
欲了解更多信息,请查看:
Design pattern – Inversion of control and Dependency injection.
【讨论】:
据我所知,“反转”一词的使用取决于这样一个事实,即接口被认为是比依赖它的服务更高级别的抽象。 倒转的是抽象依赖的方向:你的服务不再依赖于低级事物,而是依赖于更高层次的事物。
让我们考虑一个简化的例子。
FooService 依赖于BarDatabase:我们的服务依赖于数据库实现。值得注意的是,我们的服务依赖于较低级别的“事物”。FooService 依赖于DatabaseInterface,而BarDatabase 又由BarDatabase 实现。由于接口被认为是比服务更高级的抽象,我们的服务现在依赖于更高级别的“事物”。现在,从某种意义上说,依赖的方向性没有改变。在实践中,FooService 仍然间接依赖于BarDatabase。值得强调的是,当我们说我们已经反转了依赖关系时,我们并不是说BarDatabase 现在以某种方式依赖于FooService。
我们的意思是,我们的服务现在不再依赖于抽象阶梯较低的东西,而是依赖于更高的东西。我们已经“颠倒”了我们的服务需要爬升以获取其依赖项的方向。
对于为什么这是好事,我会听从广泛可用的极好的解释,但直觉是依赖比你自己更抽象的事物会使你与外部事物的耦合不那么紧密,这反过来又与封装和关注点分离等好东西密切相关。
【讨论】: