这篇文章主要引用博客园 一枝花算不算浪漫的文章
1.IOC理论背景
在面向对象设计方法设计的软件系统中,底层是由N个对象组成的,系统的功能是由对象间的合作来实现的。

齿轮的这种关系就和对象之间的耦合关系一样,虽然对象之间的耦合关系无法避免,是协同工作的基础,但是随着系统规模的变大,功能变复杂,对象直接的依赖关系越来越复杂,这时候想弄清楚对象之间的关系就没那么容易,而且一个对象出问题就会造成“牵一发而动全身”的情况。IOC的出现就是为了解决这个问题

2. IOC是什么
IOC是Inversion of Control的缩写,翻译成中文就是“控制反转”。这种设计思想可以将复杂系统分解成相互合作的对象,降低对象之间的耦合度。。IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,如下图:

把上图中间的IOC容器拿掉,然后再来看看这套系统:

2.1 IOC到底反转在哪
软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
3. IOC的别名:依赖注入(DI)
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
3.1 举个例子
我们举一个生活中的例子,来帮助理解依赖注入的过程。大家对USB接口和USB设备应该都很熟悉吧,USB为我们使用电脑提供了很大的方便,现在有很多的外部设备都支持USB接口。

电脑主机读取文件的时候,它一点也不会关心USB接口上连接的是什么外部设备,而且它确实也无须知道。它的任务就是读取USB接口,挂接的外部设备只要符合USB接口标准即可。
如果给电脑主机接上一个U盘,主机就从U盘上读取数据,如果接上的是移动硬盘,就从移动硬盘读取数据,主机不需要关注接口接的是什么,U盘和移动硬盘也不需要关注插在电视还是电脑,这个决定权在于“我”,我就起到了IOC容器的作用。
3.2 应用到软件系统
我们把依赖注入应用到软件系统中,再来描述一下这个过程:
对象A依赖于对象B,当对象 A需要用到对象B的时候,IOC容器就会立即创建一个对象B送给对象A。IOC容器就是一个对象制造工厂,你需要什么,它会给你送去,你直接使用就行了,而再也不用去关心你所用的东西是如何制成的,也不用关心最后是怎么被销毁的,这一切全部由IOC容器包办。
在传统的实现中,由程序内部代码来控制组件之间的关系。我们经常使用new关键字来实现两个组件之间关系的组合,这种实现方式会造成组件之间耦合。IOC很好地解决了该问题,它将实现组件间关系从程序内部提到外部容器,也就是说由容器在运行期将组件间的某种依赖关系动态注入组件中。
4. IOC有什么好处
- 可维护性比较好,非常便于进行单元测试,便于调试程序和诊断故障。代码中的每一个Class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可
- 每个开发团队的成员都只需要关心实现自身的业务逻辑,完全不用去关心其它的人工作进展,因为你的任务跟别人没有任何关系(解耦),你的任务可以单独测试,你的任务也不用依赖于别人的组件,再也不用扯不清责任了
- 同一个USB外部设备可以插接到任何支持USB的设备,可以插接到电脑主机,也可以插接到DV机,USB外部设备可以被反复利用。在软件工程中,这种特性就是可复用性好,我们可以把具有普遍性的常用组件独立出来,反复利用到项目中的其它部分,或者是其它项目,当然这也是面向对象的基本特征。显然,IOC不仅更好地贯彻了这个原则,提高了模块的可复用性。符合接口标准的实现,都可以插接到支持此标准的模块中
- 同USB外部设备一样,模块具有热插拔特性。IOC生成对象的方式转为外置方式,也就是把对象生成放在配置文件里进行定义,这样,当我们更换一个实现子类将会变得很简单,只要修改配置文件就可以了,完全具有热插拨的特性
IOC是一种设计思想,只要理解了这种思想,就知道为什么IOC如此之重要了。