什么是容器?什么是控制反转?什么是依赖注入?

控制反转控制反转(Inversion of Control) , 简称IoC , 它不是一门技术 , 而是一种设计思想 , 一个重要的面向对象编程的法则 。它能指导我们如何设计出松耦合、更优良的程序 。
传统应用程序都是由我们在类内部主动创建依赖对象 , 从而导致类与类之间高耦合 , 难于测试 。如下图所示:

什么是容器?什么是控制反转?什么是依赖注入?

文章插图
图一
但有了IoC容器后 , 我们可以把创建和查找依赖对象的控制权交给了容器 , 由容器进行注入组合对象 , 所以对象与对象之间是松散耦合 , 这样也方便测试 , 利于功能复用 , 更重要的是使得程序的整个体系结构变得非常灵活 。如下图所示:
什么是容器?什么是控制反转?什么是依赖注入?

文章插图
图二
依赖注入依赖注入(Dependency Injection) , 简称DI  , 它也不是一门技术 , 它是一种实现 IoC 的方式 , 是组件之间依赖关系由容器在运行期决定 , 形象的说 , 即由容器动态的将某个依赖关系注入到组件之中 。
依赖注入的目的并非为软件系统带来更多功能 , 而是为了提升组件重用的频率 , 并为系统搭建一个灵活、可扩展的平台 。通过依赖注入机制 , 我们只需要通过简单的配置 , 而无需任何代码就可指定目标需要的资源 , 完成自身的业务逻辑 , 而不需要关心具体的资源来自何处 , 由谁实现 。如图二所示 。
什么是容器?容器是一种为某种特定组件的运行提供必要支持的一个软件环境 。例如 , Tomcat就是一个Servlet容器 , 它可以为Servlet的运行提供运行环境 。类似Docker这样的软件也是一个容器 , 它提供了必要的linux环境以便运行一个特定的Linux进程 。
在这里 , 容器就是指实现自动管理对象依赖关系 , 避免手工管理存在的缺陷 , 管理对象生命周期的环境 。
下面用伪代码来说明 , 容器、控制反转、依赖注入三者之间的关系 。
我们知道电脑一般有接入外置键盘、鼠标、U 盘的能力 。如下:
什么是容器?什么是控制反转?什么是依赖注入?

文章插图
 
但是这个能力一般要依赖USB接口 , 如下:
什么是容器?什么是控制反转?什么是依赖注入?

文章插图
 
如果不使用依赖注入 , 我们一般会采用直接在程序内部new一个对象的方式 , 如下:
什么是容器?什么是控制反转?什么是依赖注入?

文章插图
 
在永不升级的时候 , 这样做是没有太大问题的 , 因为我们同样可以实现一次操作终生使用的效果 。但现实是即使强大的神机也会面临岁月的折磨 , 我们的 USB 接口同样在某天会变得老化 , 速度颇慢 , 跟不上时代的步伐 , 更不兼容最新的 Type-C 接口 。于是我们需要升级 , 但是 , 如果像之前那样直接new , 那你需要直接修改核心逻辑 , 如果有多个地方使用 , 那你就需要修改多个地方 。就等同于你要更换一个USB 接口 , 那你需要更换主板(忽略处理器、内存等接口版本差异) , 拆机、装机、插跳线、配置 BIOS 等工作 , 极其麻烦 。那我们是否可以将这个工作交给 别人 来完成 , 从而我们仅仅当一个电脑的使用者就好?
将这个复杂的工作、控制权交给所谓的“别人”替我们完成的思想就叫做 控制反转 。
而我们将这项工作移交给 帮手 来完成 , 交给帮手完成的操作实现就是 依赖注入 。
依赖注入有两种方式 , 一种是通过构造函数 , 如下构造函数中的Helper参数:
什么是容器?什么是控制反转?什么是依赖注入?

文章插图
 
另一种是通过setter方法进行赋值 。
从上图我们可以看到 , 只要我们通过$helper注入不同的USB接口对象 , 这台Computer就可以实现不同的USB切换 。
虽然 , 现在可以实现依赖注入 , 但是每次都需要我们手动传递 。如果这样的依赖注入有很多 , 后期维护将是一个繁杂的工程 。


推荐阅读