什么是控制反转,何时应该使用它?


Answers:


62

IoC(请参阅Wikipedia上的Inversion of Control)适用于组件无法完全执行任务的情况,因为该组件没有某些必要的信息或功能。

IoC模式的最简单示例是C中的回调函数。例如,您可以声明该函数:

void Iterator(void *list, Func* f)

迭代listf功能应用于每个项目。该Iterator函数不知道每个项目将如何处理,您只是提供一个函数作为参数,然后对其进行处理。

如前面的示例所示,IoC允许您将程序解耦为彼此不认识的单独组件。IoC的最常见版本之一是依赖注入

依赖注入中,每个组件都必须声明执行其任务所需的依赖关系列表。在运行时,称为IoC容器的特殊组件(通常)在这些组件之间执行绑定。它尝试为发布的组件依赖关系提供值。

这是伪代码示例:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

在此示例中,类Foo具有一个构造函数,该构造函数需要type的参数Boo才能执行某些操作。

您可以Foo使用类似于以下代码的方法创建类的实例:

MyContainer.Create(typeof Foo)

MyContainer-是一个IoC容器,它负责获取的实例Boo并将其传递给Foo构造函数。

总而言之,IoC允许您将程序解耦为单独的部分。这很好,因为:

  • 组件可以轻松进行独立测试。
  • 程序复杂度可以降低。
  • 您可以将组件切换到另一个实现。

但是,在某些情况下,IoC会使代码难以理解。

如果您想看一下IoC实际用法的好例子,请查看Mircosoft Composite UI Application BlockCompositeWPF

希望我的解释对您有所帮助。

问候,
阿库


1
五年后,但仍然。。。这是一个很好的描述。谢谢。
Nick Hodges 2013年

4
关于IoC,在任何地方都没有太多提及的是代码变得更难阅读。如果您想编写出色的软件,那么可读性是第一要务。它甚至超过了可测试性。您可以使代码解耦远远超出其用途。
Arne Evertsson 2014年

那么,将基于接口的解决方案用于其所有依赖项的代码也基于IoC设计吗?
nikel,


4

嗨,JMS,基本上,IoC / DI允许您定义一次使用的实现,并保留容器的静态副本以供每次引用时引用。

Wikipedia可能会为您提供帮助,但是我想参考您的第二部分-是的,可以对类进行依赖注入(即,每次需要将此类类型传递给方法时,都使用此类),但最好是使用接口,因为通过这种方式,您只需在设置中重新引用即可更改所使用的提供程序,存储库等版本。

IE,说您有一个读取流的接口,并且有一个XMLStreamReader和一个SQLStreamReader实现。然后,您可以将对接口的引用传递给您的方法,然后在IoC容器中告诉它要使用哪个接口。

因此,您可以拥有公共List ReadPeople(IStreamReader reader),并在您的IoC容器设置中告诉它,每次您期望IStreamReader使用SQLStreamReader时。

然后,如果您以后改变主意,只需在一个地方(容器的设置)进行更改,无论有多少种方法要求使用IStreamReader,它都将始终是您告诉容器的默认值服务。


3

假设您有一个验证器,用于检查系统中的业务是否有效。您的“ BusinessValidator”可能具有AddressValidator类型的字段,该字段用于验证企业的地址部分。如果您想在不执行外部代码(即addressValidator代码)的情况下测试BusinessValidator,则如果您在框架中使用了某种IoC / DI,则可以在其位置轻松“注入”一个模拟的addressValidator,而不必担心测试代码超出了被测类的范围。

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.