当第一次遇到控制反转(IoC)时,它可能非常令人困惑。

这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?


当前回答

控制反转是当程序回调时得到的结果,例如gui程序。

例如,在旧学校菜单中,您可能有:

print "enter your name"
read name
print "enter your address"
read address
etc...
store in database

从而控制用户交互的流程。

在GUI程序或类似程序中,我们会说:

when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase

所以现在控制反转了。。。代替计算机以固定的顺序接受用户输入,用户控制输入数据的顺序以及数据保存在数据库中的时间。

基本上,任何带有事件循环、回调或执行触发器的东西都属于这一类。

其他回答

只回答第一部分。这是怎么一回事?

控制反转(IoC)意味着先创建依赖项的实例,然后创建类的后一个实例(可选地通过构造函数注入它们),而不是先创建类的实例,再由类实例创建依赖项实例。因此,控制反转反转程序的控制流程。调用者控制程序的控制流,而不是被调用者控制控制流(同时创建依赖项)。

控制反转是一个通用原则,而依赖注入将这一原则实现为对象图构造的设计模式(即配置控制对象如何相互引用,而不是对象本身控制如何获取对另一个对象的引用)。

将控制反转视为一种设计模式,我们需要看看我们正在反转什么。依赖注入反转了对构建对象图的控制。如果用外行的术语来说,控制反转意味着程序中控制流的改变。例如,在传统的独立应用程序中,我们有一个主要的方法,从那里控制权被传递给其他第三方库(在这种情况下,我们使用了第三方的库的功能),但通过控制反转,控制权从第三方程序库代码转移到我们的代码,因为我们正在使用第三方代码库的服务。但在程序中还有其他方面需要反转,例如调用方法和线程来执行代码。

对于那些对控制反转感兴趣的人来说,已经发表了一篇论文,概述了控制反转作为一种设计模式的更完整的图景(OfficeFloor:使用办公模式来改进软件设计http://doi.acm.org/10.1145/2739011.2739013免费下载http://www.officefloor.net/about.html).

确定的关系如下:

控制反转(用于方法)=依赖(状态)注入+连续注入+线程注入

可用控制反转的上述关系汇总http://dzone.com/articles/inversion-of-coupling-control

所以上面的数字1。什么是控制反转?维护是它为我解决的首要问题。它保证我使用的是接口,这样两个类就不会彼此亲密。

使用温莎城堡这样的容器,它可以更好地解决维护问题。能够在不更改一行代码的情况下,将一个连接到数据库的组件替换为一个使用基于文件的持久性的组件,这是非常棒的(配置更改完成了)。

一旦你进入泛型,它会变得更好。想象一下,拥有一个接收记录并发布消息的消息发布者。它不在乎它发布了什么,但它需要一个映射器将记录中的内容转换为消息。

public class MessagePublisher<RECORD,MESSAGE>
{
    public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
    {
      //setup
    }
}

我写过一次,但现在如果我发布不同类型的消息,我可以向这组代码中注入许多类型。我还可以编写映射器,将相同类型的记录映射到不同的消息。将DI与Generics结合使用使我能够编写很少的代码来完成许多任务。

哦,是的,存在可测试性问题,但它们比IoC/DI的优势更为次要。

我绝对喜欢IoC/DI。

3.当你有一个中等规模的项目时,它会变得更加合适。我会说,当你开始感到疼痛时,它就变得合适了。

对我来说,IoC/DI正在向调用对象推出依赖项。超级简单。

非技术性的答案是,在你打开引擎之前,你可以更换汽车的引擎。如果一切正常(界面),你就很好了。

由于这个问题已经有很多答案,但没有一个显示反转控制项的分解,我认为有机会给出一个更简洁和有用的答案。

控制反转是一种实现依赖反转原理(DIP)的模式。DIP声明如下:1。高级模块不应依赖于低级模块。两者都应该依赖于抽象(例如接口)。2.摘要不应依赖于细节。细节(具体实现)应该依赖于抽象。

控制反转有三种类型:

界面反转提供程序不应定义接口。相反,使用者应该定义接口,提供者必须实现它。接口反转允许消除每次添加新提供者时修改使用者的必要性。

流量反演更改流量控制。例如,您有一个控制台应用程序,要求输入许多参数,在输入每个参数后,您必须按enter键。您可以在此处应用Flow Inversion,并实现桌面应用程序,用户可以选择输入参数的顺序,用户可以编辑参数,在最后一步,用户只需按Enter键一次。

创建反转它可以通过以下模式实现:工厂模式、服务定位器和依赖注入。创建反转有助于消除类型之间的依赖关系,将依赖关系对象创建过程移到使用这些依赖关系对象的类型之外。为什么依赖关系不好?这里有几个例子:在代码中直接创建一个新对象会使测试更加困难;不重新编译就不可能更改程序集中的引用(违反OCP原则);你不能轻易地用web UI替换桌面UI。