当第一次遇到控制反转(IoC)时,它可能非常令人困惑。
这是怎么一回事?它解决了哪个问题?什么时候使用合适,什么时候不合适?
当第一次遇到控制反转(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
所以现在控制反转了。。。代替计算机以固定的顺序接受用户输入,用户控制输入数据的顺序以及数据保存在数据库中的时间。
基本上,任何带有事件循环、回调或执行触发器的东西都属于这一类。
其他回答
假设我们在酒店开会。
我们邀请了很多人,所以我们漏掉了很多壶水和很多塑料杯。
当有人想喝水时,他/她将杯子装满,喝水,然后将杯子扔在地板上。
大约一个小时后,我们的地板上覆盖着塑料杯和水。
让我们在反转控件后尝试:
想象一下,在同一地点举行同一次会议,但我们现在有一个服务员只带一个玻璃杯,而不是塑料杯(Singleton)
当有人想喝酒时,服务员会给他们一杯。他们把它喝了,然后还给服务员。
抛开卫生问题不谈,使用服务员(过程控制)更有效、更经济。
这正是Spring(另一个IoC容器,例如:Guice)所做的。Spring IoC没有让应用程序使用新的关键字(例如,拿一个塑料杯子)创建所需的东西,而是为应用程序提供所需对象(一杯水)的同一杯子/实例(singleton)。
把自己想象成这样一个会议的组织者:
示例:-
public class MeetingMember {
private GlassOfWater glassOfWater;
...
public void setGlassOfWater(GlassOfWater glassOfWater){
this.glassOfWater = glassOfWater;
}
//your glassOfWater object initialized and ready to use...
//spring IoC called setGlassOfWater method itself in order to
//offer to meetingMember glassOfWater instance
}
有用的链接:-
http://adfjsf.blogspot.in/2008/05/inversion-of-control.htmlhttp://martinfowler.com/articles/injection.htmlhttp://www.shawn-barrett.com/blog/post/Tip-of-the-day-e28093-Inversion-Of-Control.aspx
所以上面的数字1。什么是控制反转?维护是它为我解决的首要问题。它保证我使用的是接口,这样两个类就不会彼此亲密。
使用温莎城堡这样的容器,它可以更好地解决维护问题。能够在不更改一行代码的情况下,将一个连接到数据库的组件替换为一个使用基于文件的持久性的组件,这是非常棒的(配置更改完成了)。
一旦你进入泛型,它会变得更好。想象一下,拥有一个接收记录并发布消息的消息发布者。它不在乎它发布了什么,但它需要一个映射器将记录中的内容转换为消息。
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
我写过一次,但现在如果我发布不同类型的消息,我可以向这组代码中注入许多类型。我还可以编写映射器,将相同类型的记录映射到不同的消息。将DI与Generics结合使用使我能够编写很少的代码来完成许多任务。
哦,是的,存在可测试性问题,但它们比IoC/DI的优势更为次要。
我绝对喜欢IoC/DI。
3.当你有一个中等规模的项目时,它会变得更加合适。我会说,当你开始感到疼痛时,它就变得合适了。
由于这个问题已经有很多答案,但没有一个显示反转控制项的分解,我认为有机会给出一个更简洁和有用的答案。
控制反转是一种实现依赖反转原理(DIP)的模式。DIP声明如下:1。高级模块不应依赖于低级模块。两者都应该依赖于抽象(例如接口)。2.摘要不应依赖于细节。细节(具体实现)应该依赖于抽象。
控制反转有三种类型:
界面反转提供程序不应定义接口。相反,使用者应该定义接口,提供者必须实现它。接口反转允许消除每次添加新提供者时修改使用者的必要性。
流量反演更改流量控制。例如,您有一个控制台应用程序,要求输入许多参数,在输入每个参数后,您必须按enter键。您可以在此处应用Flow Inversion,并实现桌面应用程序,用户可以选择输入参数的顺序,用户可以编辑参数,在最后一步,用户只需按Enter键一次。
创建反转它可以通过以下模式实现:工厂模式、服务定位器和依赖注入。创建反转有助于消除类型之间的依赖关系,将依赖关系对象创建过程移到使用这些依赖关系对象的类型之外。为什么依赖关系不好?这里有几个例子:在代码中直接创建一个新对象会使测试更加困难;不重新编译就不可能更改程序集中的引用(违反OCP原则);你不能轻易地用web UI替换桌面UI。
维基百科文章。对我来说,控制反转就是将您按顺序编写的代码转换为委托结构。您的程序不是显式地控制一切,而是设置一个类或库,其中包含发生某些事情时要调用的某些函数。它解决了代码重复。例如,在过去,您可以手动编写自己的事件循环,在系统库中轮询新事件。现在,大多数现代API只需告诉系统库您感兴趣的事件,它会让您知道它们何时发生。控制反转是减少代码重复的一种实用方法,如果您发现自己复制了整个方法,只更改了一小段代码,可以考虑使用控制反转来解决它。在许多语言中,通过委托、接口甚至原始函数指针的概念,控制反转变得容易。它并不适合在所有情况下使用,因为这样编写时,程序的流程可能更难遵循。在编写可重用的库时,这是一种设计方法的有用方法,但除非它真的解决了代码重复问题,否则应该在自己程序的核心中谨慎使用。
在类中创建对象称为紧密耦合,Spring通过遵循设计模式(DI/IOC)来消除这种依赖性。在其中类的对象是传入构造函数而不是在类中创建的。此外,我们在构造函数中提供了超类引用变量,以定义更一般的结构。