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

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


当前回答

编程演讲

简单地说,IoC:它是使用接口作为特定对象(例如字段或参数)的一种方式,作为某些类可以使用的通配符。它允许代码的可重用性。

例如,假设我们有两个类:狗和猫。两者具有相同的品质/状态:年龄、体型、体重。因此,我可以创建一个名为AnimalService的服务类,而不是创建一个称为DogService和CatService的服务,它只允许在Dog和Cat使用IAnimal接口时使用它们。

然而,从务实的角度来看,它有一些倒退。

a) 大多数开发人员不知道如何使用它。例如,我可以创建一个名为Customer的类,我可以(使用IDE的工具)自动创建一个称为ICustomer的接口。因此,无论接口是否会被重用,找到一个充满类和接口的文件夹并不罕见。它叫做BLOATED。有些人可能会认为“也许在未来我们可以使用它”-|

b) 它有一些限制。例如,让我们讨论一下Dog和Cat的情况,我想添加一个仅针对狗的新服务(功能)。比方说,我想计算训练一只狗所需的天数(trainDays()),因为猫没用,猫不能训练(我开玩笑)。

b.1)如果我将trainDays()添加到服务AnimalService中,那么它也适用于猫,并且根本无效。

b.2)我可以在trainDays()中添加一个条件,它评估使用的类。但这将彻底打破IoC。

b.3)我可以为新功能创建一个名为DogService的新服务类。但是,这将增加代码的可维护性,因为我们将为Dog提供两类服务(具有类似的功能),这很糟糕。

其他回答

我在使用库或框架的上下文中想到了控制反转。

传统的“控制”方式是我们构建一个控制器类(通常是主类,但也可以是任何类型的),导入一个库,然后使用您的控制器类来“控制”软件组件的操作。就像你的第一个C/Python程序(继HelloWorld之后)。

import pandas as pd
df = new DataFrame()
# Now do things with the dataframe.

在这种情况下,我们需要知道Dataframe是什么才能使用它。您需要知道要使用什么方法,它的取值方式等等。如果您通过多态性将它添加到自己的类中,或者只是重新调用它,那么您的类将需要Dataframe库才能正常工作。

“控制反转”意味着过程反转。您可以注册类并将其发送回要控制的引擎,而不是您的类控制库、框架或引擎的元素。换句话说,IoC可能意味着我们正在使用代码来配置框架。您也可以将其视为类似于我们在map或filter中使用函数来处理列表中的数据的方式,只是将其应用于整个应用程序。

如果您是构建引擎的人,那么您可能正在使用依赖注入方法(如上所述)来实现这一点。如果你是一个使用引擎的人(更常见),那么你应该能够只声明类,添加适当的符号,让框架为你完成剩下的工作(例如创建路由、分配servlet、设置事件、输出小部件等)。

我觉得用这么多先前的答案回答这个问题有点尴尬,但我只是觉得任何答案都没有足够简单地说明这个概念。

所以我们开始。。。

在非IOC应用程序中,您需要对流程进行编码,并在其中包含所有详细步骤。考虑一个创建报告的程序,它将包含设置打印机连接、打印页眉、遍历详细记录、打印页脚、可能执行页面馈送等的代码。

在IOC版本的报告程序中,您将配置一个通用的、可重用的报告类的实例,即一个包含打印报告的过程流但其中没有任何详细信息的类。您提供的配置可能使用DI来指定报告应该调用哪个类来打印标题、报告应该调用什么类来打印详细信息行、,以及Report应该调用什么类来打印页脚。

因此,控制反转来自控制过程,而不是代码,而是包含在一个外部的、可重用的类(Report)中,该类允许您指定或注入(通过DI)报告的详细信息-页眉、详细信息行和页脚。

通过提供不同的细节类集,可以使用同一Report类(控制类)生成任意数量的不同报告。您通过依赖Report类来提供控件,而只是通过注入来指定报表之间的差异,从而实现了控件的反转。

在某些方面,IOC可以与驱动器备份应用程序相比较-备份总是执行相同的步骤,但备份的文件集可能完全不同。

现在具体地回答最初的问题。。。

这是怎么一回事?IOC依赖于一个可重用的控制器类,并提供针对当前问题的详细信息。它解决了哪个问题?防止您必须重述控制流程。什么时候使用合适,什么时候不合适?无论何时创建控制流始终相同且仅更改细节的流程流。在创建一次性自定义流程时,您不会使用它。

最后,IOC不是DI,DI也不是IOC——DI通常可以在IOC中使用(为了说明抽象控制类的细节)。

无论如何,我希望这有帮助。

什么是控制反转?

如果您遵循这两个简单的步骤,您就完成了控制反转:

把该做什么和什么时候该做分开。确保零件何时尽可能少地了解什么零件;反之亦然。

根据您用于实现的技术/语言,这些步骤中的每一个都有几种可能的技术。

--

控制反转(IoC)的反转部分令人困惑;因为反转是相对项。了解IoC的最好方法是忘记这个词!

--

示例

事件处理。事件处理程序(做什么部分)--引发事件(何时做部分)依赖注入。构造依赖项(做什么部分)的代码——在需要时为客户机实例化和注入依赖项,这通常由Dagger等DI工具来处理(什么时候做部分)。接口。组件客户端(何时执行部分)--组件接口实现(执行部分)x装置夹具。Setup和TearDown(要做的部分)--xUnit框架在开始时调用Setup,在结束时调用TearDown(何时做部分)模板方法设计模式。模板方法何时执行部分--基本子类实现何时执行部分COM.DllMain、DllCanUnload等中的DLL容器方法(做什么部分)--COM/OS(什么时候做部分)

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

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

这里可以找到非常简单的书面解释

http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html

上面写着-

“任何非平凡的应用程序都由两个或多个类组成相互协作以执行一些业务逻辑。传统上,每个对象都负责获得自己的对其协作对象(其依赖项)的引用。应用DI时,对象在创建时被赋予其依赖性某个外部实体在系统换句话说,依赖项被注入到对象中。"