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

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


当前回答

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

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

其他回答

编程演讲

简单地说,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提供两类服务(具有类似的功能),这很糟糕。

为了理解这个概念,控制反转(IoC)或依赖反转原理(DIP)涉及两个活动:抽象和反转。依赖注入(DI)只是为数不多的反转方法之一。

要了解更多信息,您可以在此处阅读我的博客

这是怎么一回事?

这是一种让实际行为来自边界之外的实践(面向对象编程中的类)。边界实体只知道它的抽象(例如面向对象编程中的接口、抽象类、委托)。

它解决了什么问题?

在编程方面,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

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

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

例如,任务#1是创建对象。没有IOC概念,任务#1应该由程序员完成。但有了IOC概念后,任务#1将由容器完成。

简而言之,控件从编程器转换为容器。因此,它被称为控制反转。

我在这里找到了一个很好的例子。

控制反转意味着您控制组件(类)的行为。为什么称之为“反转”,因为在这种模式之前,类是硬连线的,并且确定了它们将要做什么。

导入具有TextEditor和SpellChecker类的库。现在,这个拼写检查器自然只检查英语的拼写。假设您希望TextEditor处理德语并能够进行拼写检查,那么您可以控制它。

在IoC的情况下,这种控制是反向的,即它是如何给你的?库将实现如下内容:

它将有一个TextEditor类,然后会有一个ISpellChecker(它是一个接口,而不是一个具体的SpellChecker类),当您在IoC容器中配置东西时,例如Spring,您可以提供自己的“ISpellChecker”实现,它将检查德语的拼写。因此,拼写检查将如何工作的控制权是从该库中获取并交给您的。这是IoC。