有许多类会依赖一个或多个底层的资源 。 例如,拼写检查器需要依赖词典 。 因此,像下面这样把类实现为静态工具类的做法并不少见(详见第 4 条):
// Inappropriate use of static utility - inflexible & untestable!
public class SpellChecker {
private static final Lexicon dictionary = ...;
private SpellChecker() {} // Noninstantiable
public static boolean isValid(String word) { ... }
public static List<String> suggestions(String typo) { ... }
}
同样地,将这些类实现为 Singleton 的做法也并不少见(详见第 3 条) :
// Inappropriate use of singleton - inflexible & untestable!
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) { ... }
}
以上两种方法都不理想,因为它们都是假定只有一本词典可用 。 实际上,每一种语言都有自己的词典,特殊同汇还要使用特殊的词典 。 此外,可能还需要用特殊的词典进行测试 。 因此假定用一本词典,就能满足所有需求,这简直是痴心妄想 。
建议尝试用 SpellChecker 来支持多词典,即在现有的拼写检查器中,设 dictionary域为 nonfinal ,并添加一个方法用它来修改词典,但是这样的设置会显得很笨拙、容易出错,并且无法并行工作 。 静态工具类和 Singleton 类不适合于需要引用底层资源的类 。
这里需要的是能够支持类的多个实例(在本例中是指 SpellChecker ),每一个实例都使用客户端指定的资源(在本例中是指词典) 。 满足该需求的最简单的模式是, 当创建一个新的实例时 , 就将该资源传到构造器中 。 这是依赖注入( dependency injection )的一种形式:词典(dictionary )是拼写检查器的一个依赖( depend ency ),在创建拼写检查器时就将词典注入( injected )其中 。
// Dependency injection provides flexibility and testability
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) { ... }
}
依赖注入模式就是这么简单,因此许多程序员使用多年,却不知道它还有名字呢 。 虽然这个拼写检查器的范例中只有一个资源(词典),但是依赖注入却适用于任意数量的资源,以及任意的依赖形式 。 依赖注入的对象资源具有不可变性,因此多个客户端可以共享依赖对象(假设客户端们想要的是同一个底层资惊)。依赖注入也同样适用于构造器、静态工厂和构建器 。
这个程序模式的另一种有用的变体是,将资源工厂( factory )传给构造器 。 工厂是可以被重复调用来创建类型实例的一个对象 。 这类工厂具体表现为工厂方法( Factory Method) 。 在 Java 8 中增加的接口 SupplierT>,最适合用于表示工厂 。带有 Supplier<T>的方法,通常应该限制输入工厂的类型参数使用有限制的通配符类型( bounded wildcard type ),以便客户端能自多传入一个工厂,来创建指定类型的任意子类型 。 例如,下面是一个生产马赛克的方法,它利用客户端提供的工厂来生产每一片马赛克 :
Mosaic create(Supplier<? extends Tile> tileFactory) { ... }
虽然依赖注入极大地提升了灵活性和可测试性,但它会导致大型项目凌乱不堪,因为它通常包含上千个依赖 。 不过这种凌乱用一个依赖、注入框架( dep endency injection framework )便可以终结,如 Dagger 、Guice或者 Spring。 文章来源:https://www.toymoban.com/news/detail-554586.html
总而言之,不要用 Singleton 和静态工具类来实现依赖一个或多个底层资源的类,且该资源的行为会影响到该类的行为;也不要直接用这个类来创建这些资源 。 而应该将这些资源或者工厂传给构造器(或者静态工厂,或者构建器),通过它们来创建类 。 这个实践就被称作依赖注入,它极大地提升了类的灵活性 、 可重用性和可测试性 。文章来源地址https://www.toymoban.com/news/detail-554586.html
到了这里,关于Effective Java笔记(5)优先考虑依赖注入来引用资源的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!