当第一次遇到控制反转(IoC)时,它可能非常令人困惑。
这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?
当第一次遇到控制反转(IoC)时,它可能非常令人困惑。
这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?
当前回答
控制反转意味着您控制组件(类)的行为。为什么称之为“反转”,因为在这种模式之前,类是硬连线的,并且确定了它们将要做什么。
导入具有TextEditor和SpellChecker类的库。现在,这个拼写检查器自然只检查英语的拼写。假设您希望TextEditor处理德语并能够进行拼写检查,那么您可以控制它。
在IoC的情况下,这种控制是反向的,即它是如何给你的?库将实现如下内容:
它将有一个TextEditor类,然后会有一个ISpellChecker(它是一个接口,而不是一个具体的SpellChecker类),当您在IoC容器中配置东西时,例如Spring,您可以提供自己的“ISpellChecker”实现,它将检查德语的拼写。因此,拼写检查将如何工作的控制权是从该库中获取并交给您的。这是IoC。
其他回答
维基百科文章。对我来说,控制反转就是将您按顺序编写的代码转换为委托结构。您的程序不是显式地控制一切,而是设置一个类或库,其中包含发生某些事情时要调用的某些函数。它解决了代码重复。例如,在过去,您可以手动编写自己的事件循环,在系统库中轮询新事件。现在,大多数现代API只需告诉系统库您感兴趣的事件,它会让您知道它们何时发生。控制反转是减少代码重复的一种实用方法,如果您发现自己复制了整个方法,只更改了一小段代码,可以考虑使用控制反转来解决它。在许多语言中,通过委托、接口甚至原始函数指针的概念,控制反转变得容易。它并不适合在所有情况下使用,因为这样编写时,程序的流程可能更难遵循。在编写可重用的库时,这是一种设计方法的有用方法,但除非它真的解决了代码重复问题,否则应该在自己程序的核心中谨慎使用。
为了理解IoC,我们应该讨论依赖反转。
依赖反转:依赖于抽象,而不是具体。
控制反转:主与抽象,以及主如何成为系统的粘合剂。
我写了一些很好的例子,你可以在这里查看:
https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/
https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/
https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/
我在使用库或框架的上下文中想到了控制反转。
传统的“控制”方式是我们构建一个控制器类(通常是主类,但也可以是任何类型的),导入一个库,然后使用您的控制器类来“控制”软件组件的操作。就像你的第一个C/Python程序(继HelloWorld之后)。
import pandas as pd
df = new DataFrame()
# Now do things with the dataframe.
在这种情况下,我们需要知道Dataframe是什么才能使用它。您需要知道要使用什么方法,它的取值方式等等。如果您通过多态性将它添加到自己的类中,或者只是重新调用它,那么您的类将需要Dataframe库才能正常工作。
“控制反转”意味着过程反转。您可以注册类并将其发送回要控制的引擎,而不是您的类控制库、框架或引擎的元素。换句话说,IoC可能意味着我们正在使用代码来配置框架。您也可以将其视为类似于我们在map或filter中使用函数来处理列表中的数据的方式,只是将其应用于整个应用程序。
如果您是构建引擎的人,那么您可能正在使用依赖注入方法(如上所述)来实现这一点。如果你是一个使用引擎的人(更常见),那么你应该能够只声明类,添加适当的符号,让框架为你完成剩下的工作(例如创建路由、分配servlet、设置事件、输出小部件等)。
这是怎么一回事?反转(耦合)控制,更改方法签名的耦合方向。对于反向控制,方法签名的定义由方法实现(而不是方法的调用方)决定。此处完整解释
它解决了哪个问题?方法上的自顶向下耦合。这随后消除了重构的需要。
什么时候使用合适,什么时候不合适?对于定义良好的小型应用程序,如果没有太大的变化,可能会产生开销。然而,对于将要发展的定义较少的应用程序,它减少了方法签名的固有耦合。这使开发人员可以更自由地开发应用程序,避免了对代码进行昂贵的重构。基本上,允许应用程序在很少返工的情况下发展。
我已经读了很多关于这一点的答案,但如果有人仍然感到困惑,需要一个额外的“外行术语”来解释IoC,我的看法是:
想象一个父母和孩子彼此交谈。
没有IoC:
*家长:我问你问题时你才能说话,我允许你时你才能行动。
家长:这意味着,如果我不问你,你就不能问我你能不能吃饭、玩、上厕所甚至睡觉。
家长:你想吃吗?
孩子:没有。
家长:好的,我会回来的。等我。
孩子:(想玩,但由于家长没有问题,孩子什么都不会做)。
1小时后。。。
家长:我回来了。你想玩吗?
孩子:是的。
父级:已授予权限。
孩子:(终于可以玩了)。
这个简单的场景解释了控件以父级为中心。孩子的自由受到限制,高度依赖于父母的问题。孩子只有在被要求说话时才能说话,只有在获得许可时才能行动。
使用IoC:
孩子现在有能力提出问题,家长可以回答并获得许可。简单地说就是控制颠倒了!孩子现在可以随时提问,尽管在权限方面仍然依赖于家长,但他不依赖于说话/提问的方式。
从技术上解释,这与console/shell/cmd与GUI交互非常相似。(这是马克·哈里森的答案,排名第二)。在控制台中,您依赖于向您询问/显示的内容,如果不先回答问题,您无法跳转到其他菜单和功能;遵循严格的顺序流程。(编程上这就像一个方法/函数循环)。然而,有了GUI,菜单和功能就被布置好了,用户可以选择所需的任何内容,从而拥有更多的控制权和更少的限制。(以编程方式,菜单在选中并执行操作时具有回调)。