当第一次遇到控制反转(IoC)时,它可能非常令人困惑。
这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?
当第一次遇到控制反转(IoC)时,它可能非常令人困惑。
这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?
当前回答
控制反转是将控制权从库转移到客户端。当我们讨论将函数值(lambda表达式)注入(传递)到控制(改变)库函数行为的高阶函数(库函数)中的客户端时,它更有意义。
因此,这个模式的一个简单实现(具有巨大的含义)是一个更高阶的库函数(它接受另一个函数作为参数)。库函数通过赋予客户端提供“控制”函数作为参数的能力来传递对其行为的控制。
例如,“map”、“flatMap”等库函数是IoC实现。
当然,例如,有限的IoC版本是布尔函数参数。客户端可以通过切换布尔参数来控制库函数。
将库依赖项(承载行为)注入到库中的客户端或框架也可以被视为IoC
其他回答
使用IoC,您不会对对象进行更新。您的IoC容器将做到这一点,并管理它们的生命周期。
它解决了必须手动将一种类型对象的每个实例化更改为另一种类型的问题。
如果您的功能将来可能会发生变化,或者根据中使用的环境或配置而有所不同,则使用此选项是合适的。
控制反转是关于分离关注点。
没有IoC:你有一台笔记本电脑,你不小心弄坏了屏幕。糟糕的是,你发现市场上没有同一型号的笔记本电脑屏幕。所以你被卡住了。
IoC:你有一台台式电脑,你不小心把屏幕弄坏了。你发现你可以从市场上买到几乎所有的桌面显示器,而且它与你的桌面很好地配合。
在这种情况下,您的桌面成功地实现了IoC。它接受各种类型的显示器,而笔记本电脑不接受,它需要一个特定的屏幕来固定。
真的不明白为什么会有很多错误的答案,甚至被接受的答案也不太准确,这让人很难理解。真相总是简单明了的。
正如@Schneider在@Mark Harrison的回答中所评论的,请阅读Martin Fowler关于IoC的帖子。
https://martinfowler.com/bliki/InversionOfControl.html
我最喜欢的是:
这种现象就是控制反转(也称为好莱坞原则——“不要打电话给我们,我们会打电话给你”)。
为什么?
IoC的Wiki,我可以引用一段话。
控制反转用于增加程序的模块性并使其可扩展。。。随后在2004年由Robert C.Martin和Martin Fowler进一步推广。
Robert C.Martin:《清洁代码:敏捷软件工艺手册》的作者。
马丁·福勒:《重构:改进现有代码的设计》一书的作者。
在使用“控制反转”之前,你应该充分了解它的优点和缺点,如果你这样做,你应该知道为什么要使用它。
赞成的意见:
您的代码被解耦,因此您可以轻松地将接口的实现与其他实现交换它是针对接口而非实现进行编码的强大动力为代码编写单元测试是非常容易的,因为它只依赖于它在构造函数/setter中接受的对象,并且可以很容易地用正确的对象单独初始化它们。
欺骗:
IoC不仅会反转程序中的控制流,还会使其变得相当模糊。这意味着你不能再只读取代码并从一个地方跳到另一个地方,因为代码中通常存在的连接不再存在。相反,它在XML配置文件或注释中以及IoC容器的代码中解释这些元数据。出现了一类新的错误,即您的XML配置或注释错误,您可以花费大量时间来找出IoC容器在特定条件下向其中一个对象注入空引用的原因。
就我个人而言,我看到了IoC的优点,我非常喜欢它们,但我倾向于尽可能避免使用IoC,因为它将您的软件变成一个类的集合,这些类不再构成“真正的”程序,而只是需要通过XML配置或注释元数据组合在一起的东西,如果没有IoC,它就会崩溃。
我喜欢这样的解释:http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
它开始很简单,还显示了代码示例。
消费者X需要被消费的类Y来完成某件事。这一切都很好,很自然,但X真的需要知道它使用Y吗?
如果X知道它使用的东西具有Y的行为、方法、财产等,而不知道谁真正实现了这些行为,这还不够吗?
通过提取X在Y中使用的行为的抽象定义(如下面的I所示),并让消费者X使用该行为的实例而不是Y,它可以继续做它所做的事情,而不必知道Y的细节。
在上图中,Y实现了I,X使用了I的一个实例。虽然很可能X仍然使用Y,但有趣的是X并不知道这一点。它只知道它使用了实现I的东西。
阅读文章了解更多信息和好处描述,如:
X不再依赖于Y更灵活,可以在运行时决定实现隔离代码单元,更容易测试
...