Item5-宁可依赖注入而不要使用硬编码
作者:互联网
引子
才疏学浅,坚持每天读一小节《effective JAVA 第三版 原版》,翻译的有些生硬,不过会坚持下去!
正文
很多类依赖一个或更多的底层资源。举个例子,一个拼写检查器依赖于一本字典。将这种类实现为静态实例程序类并不少见。
// 在此使用静态实例是不合适的 - 死板 & 无法测试
public class SpellChecker{
private static final Lexicon dictionary = ...;
private SpellChecker() {} // 不可实例化
public static boolean isValid(String word) {...}
public static List<String> suggestions(String typo) {...}
}
类似地,将它们实现为单例也并不少见。
// 使用单例不合适 - 死板 & 无法测试
public class SpellChecker{
private final Lexicon dictionary = ...;
private SpellChecker(...) {}
public static INSTANCE = new SpellChecker(...);
public boolean isValid(String word) {...}
public List<String> suggestions(String typo) {...}
}
这两种方法都让人不满意。因为这些做法假定只有一本字典可以使用。事实上,每一种语言都有它自己独有的字典,并且每一本字典都有独有的词汇表。另外,也许会使用一本特别的字典做测试,如果认为一本词典就足够了,这就是一厢情愿的想法。
你可以尝试使字段 dictionary 非 final 并且添加方法去改变现有的拼写检查器,让 SpellChecker 支持多种字典。但是这种办法在目前的设定里是愚蠢的、易出错的、难以实行的。Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.(静态实例类和单例对象不适用于其行为由底层资源参数化的类。)
我们所需要的是支持该类的拥有多个实例的能力(本例中,SpellChecker),每个实例使用的资源由客户需求来决定(本例中,dictionary)。一种简单的模式是,当创建一个实例时,通过构造器去创建去满足需求即可。这是一种依赖注入:字典是拼写检查器的依赖项,在创建拼写检查器时将其注入。
// 依赖注入提供了灵活性和可测试性
public class SpellChecker{
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary){
this.dictionary = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) { ... }
public List<String> suggestions(String typo) { ... }
}
依赖注入这种模式很简单,以致于许多程序员使用了很多年都不清楚它的名字叫什么。尽管我们的拼写检查器例子只有一个简单资源(字典),但是依赖项注入可以处理任意数量的资源和任意的依赖关系图。依赖注入等同于适用的构造函数、静态工厂和建造者。
模式的一个有用变体是将资源工厂传递给构造函数。工厂是一个对象,可以反复调用它来创建类型的实例。比如:工厂方法模式。Java 8 提供了新的接口:
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
此接口是工厂的绝佳体现。它允许用户通过工厂创建任何特殊类型的子类型。
尽管依赖注入极大的提升了灵活性和可测试性,但会让包含了数以千计依赖的大项目变得散乱。我们可以使用优秀的依赖注入框架,Dagger,Guice 或者 Spring。
总之,不要使用单例或静态实例类来实现依赖于一个或多个底层资源的类,这些底层资源的行为会影响类的行为,并且不要让类直接创建这些资源。相应的,通过资源或者工厂去创建它们,构造器或者静态工厂或者建造者。掌握依赖注入,将会极大地提高类的灵活性、可重用性和可测试性。
标签:编码,依赖,dictionary,...,宁可,Item5,SpellChecker,实例,public 来源: https://blog.csdn.net/Crazypokerk_/article/details/96560201