我已经看到很多有关依赖注入(DI)和控制反转(IOC)的参考,但是我真的不知道它们之间是否有区别。

我会喜欢开始使用它们中的一个或两个,但是我对它们的区别有些困惑。

评论

控制反转通常是指“容器”,而依赖注入是指实际模式。但是他们并驾齐驱。我建议阅读Martin Fowler的文章以了解该主题。

依赖注入是您要做的事情,它会导致一个称为控制反转的命令结构。它们具有内在的联系。

DI是IoC的一种形式,我在此答案中对DI和IoC进行了非常详细的解释

我想说DI是IOC的特例。传统控制从模块管理器转到模块->请求模块,在DI中将其转换为模块管理器->从模块获取请求的依赖项。

因此,换句话说,IoC基本上是使用DI的实现。我能正确理解吗?

#1 楼

定义

控制反转是一种设计范例,其目的是减少对应用程序框架代码对具体实现的了解,并为应用程序的领域特定组件提供更多控制。在传统的自上而下设计的系统中,应用程序的逻辑流程和依赖关系意识从最先设计的组件到最后设计的组件。因此,控制反转几乎是应用程序中控制权和依赖项意识的字面反转。

一起工作

控制反转可以利用依赖注入,因为需要一种机制来创建提供特定功能的组件。存在和使用其他选项,例如激活器,工厂方法等,但是当框架类可以接受所需的依赖项时,框架不需要引用这些实用工具类。

示例

这些概念在起作用的一个示例是Reflector中的插件框架。即使应用程序在编译时对插件一无所知,插件也具有对系统的大量控制权。在这些插件中的每个插件上都调用一个方法,如果有内存,则将其初始化,从而将控制权传递给插件。该框架不知道他们将要做什么,只是让他们去做。控制已从主应用程序获取,并交给了执行特定工作的组件;控制反转。

该应用程序框架允许通过各种服务提供商访问其功能。插件在创建时会获得对服务提供商的引用。这些依赖关系允许插件添加自己的菜单项,更改文件的显示方式,在适当的面板中显示其自身的信息等。由于依赖关系是通过接口传递的,因此实现可以更改,并且更改不会破坏只要合同保持原样,就可以使用这些代码。如今,有一些工具(MEF用于其中之一)在注入依赖项时提供了更多选择,其中包括应用程序框架可以接受一系列插件作为依赖项的功能。

摘要

虽然可以使用这些概念并独立提供好处,但是它们一起允许编写更加灵活,可重用和可测试的代码。因此,它们是设计面向对象解决方案的重要概念。

评论


不,IoC是一个较旧的概念,它独立于DI(不依赖于IoC)。例如,采用Struts框架(Java):它高度依赖IoC,但不使用DI。

–罗杰里奥
15年6月28日在16:24

@Rogério-您很好地指出了这两个概念并不需要。我更新了答案以澄清这一点,然后快速描述一些框架如何将它们一起使用以允许更松散地耦合的代码。

–卡盘
15年6月28日在18:26

IoC的最简单应用程序可能是ActionListener。事件处理代码不是按程序处理代码,而是委托给自定义代码。从而反转控制。

– Mike
17年5月17日在10:10



#2 楼

了解IOC和DI的好文章http://martinfowler.com/articles/injection.html

IOC(控制反转)

IOC的意思是



编码到接口(一个组件应依赖于其他组件的接口而不是impl),并且
例如

interface iComp_2 {...}

class Comp_1 {
    iComp_2 c2 = ….;
}



删除组件实现特定的代码
例如

Comp_1 {
    iComp_2 c2 = getComp_2_Impl(); // not new Comp_2_Impl();
}



IOC可以通过以下任一方法实现:

1。 DI(依赖注入)

3 types of DI

1.1 Constructor Injection

1.2 Setter Injection

1.3 Interface Injection


2。服务定位器

DI(依赖性注入)容器

运行时隐式确定而不是编译时:在运行时根据一些配置文件确定要使用的接口的具体实现(因此在编译时,我们不知道将使用哪个impl,从而增加了应用程序的可配置性。它是在“运行时”确定不同模块之间的具体关系的实现。

依赖注入后实例化impl的实例:确定impl后,它首先通过创建其所有依赖关系来实例化impl (在配置文件中指定),然后将这些依赖项注入到实例生命周期管理中:DI容器通常仅保留对其管理生命周期所需的对象的引用,或者将其重复用于将来的注射,例如单身或轻量级。当配置为每次调用容器创建某些组件的新实例时,容器通常只会忘记创建的对象。否则,垃圾收集器在不再使用时将很难收集所有这些对象。

评论


您真的读过“注射”文章吗?国际奥委会并不完全代表这个答案。

–罗杰里奥
15年6月28日在16:26

#3 楼

我会说“控制反转”是一种设计系统的方式,其中所有模块都被视为抽象实体。

,“依赖注入”是一种实现,其中不同模块之间的具体关系是在“运行时”决定。

#4 楼

控制反转是一个通用概念,在功能语言中,通常使用延续来完成。让我们编写一个API,其中双方都是“调用方”,而没有一个都是“被调用方”。在其他更静态的环境中,您没有此功能,因此您需要此技巧才能在控制流中插入提示。