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

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


当前回答

使用IoC,您不会对对象进行更新。您的IoC容器将做到这一点,并管理它们的生命周期。

它解决了必须手动将一种类型对象的每个实例化更改为另一种类型的问题。

如果您的功能将来可能会发生变化,或者根据中使用的环境或配置而有所不同,则使用此选项是合适的。

其他回答

控制反转是关于分离关注点。

没有IoC:你有一台笔记本电脑,你不小心弄坏了屏幕。糟糕的是,你发现市场上没有同一型号的笔记本电脑屏幕。所以你被卡住了。

IoC:你有一台台式电脑,你不小心把屏幕弄坏了。你发现你可以从市场上买到几乎所有的桌面显示器,而且它与你的桌面很好地配合。

在这种情况下,您的桌面成功地实现了IoC。它接受各种类型的显示器,而笔记本电脑不接受,它需要一个特定的屏幕来固定。

这是怎么一回事?反转(耦合)控制,更改方法签名的耦合方向。对于反向控制,方法签名的定义由方法实现(而不是方法的调用方)决定。此处完整解释

它解决了哪个问题?方法上的自顶向下耦合。这随后消除了重构的需要。

什么时候使用合适,什么时候不合适?对于定义良好的小型应用程序,如果没有太大的变化,可能会产生开销。然而,对于将要发展的定义较少的应用程序,它减少了方法签名的固有耦合。这使开发人员可以更自由地开发应用程序,避免了对代码进行昂贵的重构。基本上,允许应用程序在很少返工的情况下发展。

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

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

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

确定的关系如下:

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

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

我已经读了很多关于这一点的答案,但如果有人仍然感到困惑,需要一个额外的“外行术语”来解释IoC,我的看法是:

想象一个父母和孩子彼此交谈。

没有IoC:

*家长:我问你问题时你才能说话,我允许你时你才能行动。

家长:这意味着,如果我不问你,你就不能问我你能不能吃饭、玩、上厕所甚至睡觉。

家长:你想吃吗?

孩子:没有。

家长:好的,我会回来的。等我。

孩子:(想玩,但由于家长没有问题,孩子什么都不会做)。

1小时后。。。

家长:我回来了。你想玩吗?

孩子:是的。

父级:已授予权限。

孩子:(终于可以玩了)。

这个简单的场景解释了控件以父级为中心。孩子的自由受到限制,高度依赖于父母的问题。孩子只有在被要求说话时才能说话,只有在获得许可时才能行动。

使用IoC:

孩子现在有能力提出问题,家长可以回答并获得许可。简单地说就是控制颠倒了!孩子现在可以随时提问,尽管在权限方面仍然依赖于家长,但他不依赖于说话/提问的方式。

从技术上解释,这与console/shell/cmd与GUI交互非常相似。(这是马克·哈里森的答案,排名第二)。在控制台中,您依赖于向您询问/显示的内容,如果不先回答问题,您无法跳转到其他菜单和功能;遵循严格的顺序流程。(编程上这就像一个方法/函数循环)。然而,有了GUI,菜单和功能就被布置好了,用户可以选择所需的任何内容,从而拥有更多的控制权和更少的限制。(以编程方式,菜单在选中并执行操作时具有回调)。

我同意NilObject,但我想补充一点:

如果你发现自己复制了一个完整的方法,只修改了一小段代码,你可以考虑用控制反转来处理它

如果你发现自己到处复制和粘贴代码,你几乎总是在做错事。编码为“一次且仅一次”的设计原则。