控制反转我反转谁了?
目录
¶紧耦合
编码过程中,两个甚至多个类通过彼此的合作来实现业务逻辑,此时这些类不可避免的将产生联系
🎶如果两个类直接交互,代码的耦合度就会增加,提高维护的成本
¶案例
假如你是班长,如今班级需要打扫卫生,所以你需要安排一些学生去打扫卫生
1 | //打扫卫生的学生 |
1 | public class Test { |
¶分析
Monitor 类的 command 方法中使用 new 关键字创建了一个 Student 类的对象,这种代码的耦合度就很高,维护起来的成本就很高
如果,某一天,学校体贴学生,让专门的清洁工来打扫卫生,此时班长需要更改其内部的代码,于是 Monitor 类就不得不重构,于是代码变成了这样:
1 | public class Worker { |
假如需求再一次改变,想用其他的方式进行打扫卫生,班长没准要下命令给扫地机器人去打扫卫生了,这样下去的话,Monitor 类就非常不符合设计原则,对扩展开放,对修改关闭
¶控制反转(IoC)
需要自己不断更改已经完成的代码这样太复杂了,班长想:不如把这个安排扫地的差事交给劳动委员吧,劳动委员负责安排人员去执行班长下达的扫地命令,这样我就轻松多了
1 | //可以扫地接口 |
班长是不是省心多了,他只管下命令,该叫谁去扫地由劳动委员去负责
✨这种减少班长控制逻辑的方法称为控制反转(Inversion of Control,缩写为 IoC),它不是一种技术,而是一种思想,能够指导我们设计出松耦合的程序
🤔谁的控制被反转了?
- 在紧耦合的情况下,班长需要自己通过 new 关键字创建依赖的对象
- 通过 IoC 之后,班长制行为被发转给了劳动委员,劳动委员代替班长指派人员去扫地,班长知道劳动委员会安排人去扫地就可以了
🎶通过 IoC,可以将原本的主控制类的繁琐判断操作转化为简单的使用操作
¶依赖注入
✨依赖注入(Dependency Injection,简称 DI)是实现控制反转的主要方式
依赖注入(dependency injection)的意思为:给予调用方它所需要的事物,主要包括两部分:依赖和注入
依赖:指可被方法调用的事物
注入:指将依赖传递给调用方的过程,注入之后,调用方才会调用该依赖
🎶传递依赖给调用方,而不是让调用方直接获得依赖,这个是该设计的根本需求
✨不同角度下的调用方和依赖
- 在编程语言角度下,调用方为对象和类,依赖为变量
- 在提供服务的角度下,调用方为客户端,依赖为服务
📓简单的理解就是:将创建对象的任务转移给其他 class,并直接使用依赖项的过程,被称为依赖项注入
¶三种类型的依赖注入
✨三种类型的依赖注入方式
- 构造函数注入:依赖关系是通过 class 构造器提供的
- setter 注入:注入程序用客户端的 setter 方法注入依赖项
- 接口注入:依赖项提供了一个注入方法,该方法将把依赖项注入到传递给它的任何客户端中。客户端必须实现一个接口,该接口的 setter 方法接收依赖
🤔依赖注入有哪些作用
- 创建对象
- 知道哪些类需要那些对象
- 并提供所有这些对象
如果对象有任何更改,则依赖注入会对其进行调查,不会影响到使用这些对象的类。这样,如果将来对象发生变化,依赖注入负责为类提供正确的对象,使用依赖的类并不会发生任何的变化
¶IoC 的背后——依赖注入
一个类不应静态配置其依赖项(类应该依赖于抽象,而不是依赖于具体),而应由其他一些类从外部进行配置
✨根据这些原则,一个类应该专注于履行其职责,而不是创建履行这些职责所需的对象。 这就是依赖注入发挥作用的地方:它为类提供了必需的对象
¶依赖注入优劣分析
👍依赖注入的优势
- 帮助进行单元测试
- 由于依赖关系的初始化是由注入器组件完成的,因此减少了样板代码
- 扩展应用程序变得更加容易
- 帮助实现松耦合
😣依赖注入的劣势
- 学习起来有点复杂,如果使用过度会导致管理问题和其他问题
- 许多编译时错误被推送到运行时
- 依赖注入框架是通过反射或动态编程实现的。这可能会妨碍 IDE 自动化的使用,例如查找引用,显示调用层次结构和安全重构