优先考虑依赖注入来引用资源
preface
这条相当于对前面静态工厂方法和Singleton使用的一个拓展说明,间接引出依赖注入的使用
question
有许多类会依赖一个或多个底层的资源。例如,拼写检查器需要依赖词典。因此,像
下面这样把类实现为静态工具类的做法并不少见:
public class SpellChecker {
private static final Lexicon dictionary = Lexicon.Chinese;
private SpellChecker() {}
public static boolean isValid(String word){
return dictionary.contains(word);
}
}
同样地,将这些类实现为Singleton的做法也并不少见
public class SpellChecker {
private final Lexicon dictionary = Lexicon.Chinese;
private SpellChecker() {}
private static SpellChecker INSTANCE = new SpellChecker();
public boolean isValid(String word){
return dictionary.contains(word);
}
}
上面这两种方法的不理想,因为他们都是假定只有一本字典可用,但是对于每一种语言都会自己的字典,也会存在一些特殊的字典。所以对于字典场景,上面的代码要想能适应,只能添加个方法来根据我们需要的字典类型来初始化对应的字典,但是这样子会显得很笨拙,维护也比较辛苦。
对此,我们可以让 他们自己去找资源 变成 我们提供给他们资源,这样子他们就变得更加专注和灵活,不用再去做找资源的工作
what?
当创建一个实例时,就将该资源传到构造器中。这是依赖注入的一种模式:字典是拼写检查器的一个依赖(dependency),在创建拼写检查器时就将字典注入(injected)其中:
public class SpellChecker {
private final Lexicon dictionary;
//injected进来
private SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) {
return dictionary.contains(word);
}
}
- 依赖注入适用于任意数量的资源以及任意的依赖形式。
- 依赖注入的对象资源具有不可变性因此多个客户端可以共享依赖对象(假设客户端们想要的是同一个底层资源)。
- 依赖注入也同样适用于构造器、静态工厂(详见第1条)和构建器(详见第2条)
end
原文:虽然依赖注人极大地提升了灵活性和可测试性,但它会导致大型项目凌乱不堪,因为它通常包含上千个依赖。不过这种凌乱用一个依赖注入框架 (dependeney injection frameworki)便可以终结,如 Daggee、Guice或者Spring。