前言
这是一篇2006年的博文,作者认为当时各种对依赖注入的解释反而增加了理解的难度,所以有了此文。
翻着玩的,且省略了作者的拓展阅读部分,原文真的很短,推荐看下。
本文的样例用Java编写,所以你至少应该熟悉Java中类
的定义,以及getter
,setter
还有构造器(constructor)
的概念。当然,有其它语言类似的基础也没问题。
揭秘依赖注入
原标题: Dependency Injection Demystified
作者: James Shore
翻译: neowell
当我第一次听说“依赖注入”时,我的反应是,“依赖注什么?”,然后马上就忘了这事儿。而我终于有时间来搞懂大家都在说的这个东西时,我笑了。“就这?”
“依赖注入(Dependency Injection)”把一个5分钱的概念解释为了一个25块钱的术语。不是说这个词不好…况且它是个好工具。更不提现在谷歌上的那些热门文章只专注于花里胡哨的东西,反而忽视了基础概念。嗯,所以我想我应该用更易懂的方式为这个词说些什么。
超简易版解释
依赖注入,就是给某个对象提供一个实例化的变量。真的,就这个意思。
稍长版,第一部分:依赖非注入(Dependency Non-Injection)
在类(Classes)中有一种被称为方法(methods)的东西,让我们把这个东西叫做“依赖”。大部分人则会把这些方法称作“变量(variables)”。而当他们想显得有逼格时,又把它们称作“实例变量(instance variables)”:
public class Example {
private DatabaseThingie myDatabase;
public Example() {
myDatabase = new DatabaseThingie();
}
public void DoStuff() {
...
myDatabase.GetData();
...
}
}
比如上面这段代码,我们有一个叫“myDatabase
”的变量…呃,我是说依赖。我们通过一个空构造器来初始化它。
稍长版,第二部分:依赖注入
如果我们想给这个构造器传递参数的话,那么就是把“依赖
”给“注入
”到了这个类中。那么现在当我们使用变量(依赖)时,我们就是直接使用了被给定的对象,而不是我们自己创建的那一个:
public class Example {
private DatabaseThingie myDatabase;
public Example() {
myDatabase = new DatabaseThingie();
}
public Example(DatabaseThingie useThisDatabaseInstead) {
myDatabase = useThisDatabaseInstead;
}
public void DoStuff() {
...
myDatabase.GetData();
...
}
}
依赖注入说的就是这么些东西了,剩下的无非是基于这个主题的一些演变而已。你可以用一个方法来设置依赖(咳咳,变量),等下,这不就是一个setter
方法吗。通过调用一个定义在特殊接口里的setter
方法,你就能设置依赖。你可以把依赖变成一个接口,然后动态地传入一些你自定义的东西。随你喜欢。
稍长版,第三部分:为什么要这样做?
除此以外,在测试中也方便对类进行隔离:
// 测试类
public class ExampleTest {
TestDoStuff() {
MockDatabase mockDatabase = new MockDatabase();
// MockDatabase是DatabaseThingie的一个子类,
// 所以我们可以通过这行代码进行“注入”
Example example = new Example(mockDatabase);
example.DoStuff();
mockDatabase.AssertGetDataWasCalled();
}
}
// 原类
public class Example {
private DatabaseThingie myDatabase;
public Example() {
myDatabase = new DatabaseThingie();
}
public Example(DatabaseThingie useThisDatabaseInstead) {
myDatabase = useThisDatabaseInstead;
}
public void DoStuff() {
...
myDatabase.GetData();
...
}
}
我要说的就这些,依赖注入真的就是传递一些实例变量罢了。
完