当我们第一次遇到Inversion of Control (IOC)的时候脑袋会觉得很混乱,有几个问题会感觉很困惑
- IOC是什么?
- 它解决了什么问题
- 什么时候该用它,什么时候又该不用?
回答:
控制反转(IOC)和依赖注入(DI)都是为了从我们的代码中去掉相互依赖而产生的概念,
举个例子,假设你的项目中有一个文本编辑组件,然后你想再加一个拼写检查功能。比较正常的写法是这样的:
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
这里的代码其实就在TextEditor和SpellChecker间建立了依赖关系。
如果我们是用ioc来完成这段代码那么写法就是下面这样的:
public class TextEditor {
private IocSpellChecker checker;
public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
在第一段代码里面,我们使用(this.checker =new SpellChecker())来实例化SpellChecker,这样做就导致了TextEditor直接依赖于SpellChecker类了
在第二段代码中,我们通过在textEditor的构造方法中传入一个SpellChecker的依赖类,来创建一个实例(注意这里没有在类中直接实例化SpellChecker这个依赖)。这样做的好处就是我们可以在外面实例化依赖后,再传入给textEditor,就像下面代码的写法
SpellChecker sc = new SpellChecker(); // dependency
TextEditor textEditor = new TextEditor(sc);
就是说,现在可以由调用方来决定TextEditor里面的SpellChecker是要怎么实现,因为我们是将SpellChecker在外面创建好了之后再注入到TextEditor的。
评论1: 一个很好的例子,但是如果假设不再构造函数中传入SpellChecker,而是使用setter的形式来提供SpellChecker,(如setSpellChecker方法),那么这样还算是IOC吗?
评论2: 这样还是算的,使用set注入其实是叫做setter注入,与构造函数注入算是两种不同的注入方式,IOC是一个比较广泛的概念,IOC是有多种形式的依赖注入来实现的