5. Effective Java 第三版——使用依赖注入取代硬连接资源
Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。
在这里第一时间翻译成中文版。供大家学习分享之用。

5. 使用依赖注入取代硬连接资源(hardwiring resources)
许多类依赖于一个或多个底层资源。例如,拼写检查器依赖于字典。将此类类实现为静态实用工具类并不少见(条目 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) { ... }
}
同样地,将它们实现为单例也并不少见(条目 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) { ... }
}
这两种方法都不令人满意,因为他们假设只有一本字典值得使用。在实际中,每种语言都有自己的字典,特殊的字典被用于特殊的词汇表。另外,使用专门的字典来进行测试也是可取的。想当然地认为一本字典就足够了,这是一厢情愿的想法。
可以通过使dictionary属性设置为非final,并添加一个方法来更改现有拼写检查器中的字典,从而让拼写检查器支持多个字典,但是在并发环境中,这是笨拙的、容易出错的和不可行的。静态实用类和单例对于那些行为被底层资源参数化的类来说是不合适的。
所需要的是能够支持类的多个实例(在我们的示例中,即SpellChecker),每个实例都使用客户端所期望的资源(在我们的例子中是dictionary)。满足这一需求的简单模式是在创建新实例时将资源传递到构造方法中。这是依赖项注入(dependency injection)的一种形式:字典是拼写检查器的一个依赖项,当它创建时被注入到拼写检查器中。
// 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) { ... }
}
依赖注入模式非常简单,许多程序员使用它多年而不知道它有一个名字。 虽然我们的拼写检查器的例子只有一个资源(字典),但是依赖项注入可以使用任意数量的资源和任意依赖图。 它保持了不变性(条目 17),因此多个客户端可以共享依赖对象(假设客户需要相同的底层资源)。 依赖注入同样适用于构造方法,静态工厂(条目 1)和 builder模式(条目 2)。
该模式的一个有用的变体是将资源工厂传递给构造方法。 工厂是可以重复调用以创建类型实例的对象。 这种工厂体现了工厂方法模式(Factory Method pattern )[Gamma95]。 Java 8中引入的Supplier <T>接口非常适合代表工厂。 在输入上采用Supplier<T>的方法通常应该使用有界的通配符类型( bounded wildcard type)(条目 31)约束工厂的类型参数,以允许客户端传入工厂,创建指定类型的任何子类型。 例如,下面是一个使用客户端提供的工厂生成tile的方法:
Mosaic create(Supplier<? extends Tile> tileFactory) { ... }
尽管依赖注入极大地提高了灵活性和可测试性,但它可能使大型项目变得混乱,这些项目通常包含数千个依赖项。使用依赖注入框架(如Dagger[Dagger]、Guice[Guice]或Spring[Spring])可以消除这些混乱。这些框架的使用超出了本书的范围,但是请注意,为手动依赖注入而设计的API非常适合这些框架的使用。
总之,不要使用单例或静态的实用类来实现一个类,该类依赖于一个或多个底层资源,这些资源的行为会影响类的行为,并且不让类直接创建这些资源。相反,将资源或工厂传递给构造方法(或静态工厂或builder模式)。这种称为依赖注入的实践将极大地增强类的灵活性、可重用性和可测试性。
5. Effective Java 第三版——使用依赖注入取代硬连接资源的更多相关文章
- Effective Java 第三版——5. 使用依赖注入取代硬连接资源
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 《Effective Java 第三版》目录汇总
经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——10. 重写equals方法时遵守通用约定
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——12. 始终重写 toString 方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——14.考虑实现Comparable接口
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——18. 组合优于继承
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
随机推荐
- linux 安装wordpress 无故往外发送大量垃圾邮件
linux 安装wordpress 无故往外发送大量垃圾邮件 始末 表现出来的现象就是, 网站运行没多久,mysql服务就挂了,重启也无法启动起来,提示 No such file or dicrion ...
- Hiberante知识点梳理
Hibernate简介 Hibernat是一个ORM(关系映射)框架,对JDBC访问数据库的操作进行了简化,并且将数据库表中的字段和关系映射为对象,简化了对数据库的操作. 使用方法 读取并解析配置文件 ...
- spirngMVC的搭建
1 springMVC的搭建肯定是需要用到一系列的jar包的,那么第一步就是去spring官网下载对应版本的jar包 可以通过 http://www.cnblogs.com/imentors/p/49 ...
- C#中窗体的close,dispose,以及application.exit()的区别
close关闭窗体,对象仍然存在,调用Close函数释放资源后可能还需要再次使用. dispose,销毁对象,窗体对象被回收了,也就是不存在了,Dispose函数释放的资源不再使用. applicat ...
- 你好 JSONP !!!!
跨域与JSONP ==JSONP是解决跨域问题的一种常见方式== ==跨域问题==:因为浏览器有同源策略,所以当不同域间进行数据交互的时候就会出现跨域问题 ···· 同源策略:只有在同协议,同域名,同 ...
- linux环境
vim命令 http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html 安装YouCompleteMe 按照百度搜索的 ...
- Hue 之 SparkSql interpreters的配置及使用
1.环境说明: HDP 2.4 V3 sandbox hue 4.0.0 2.hue 4.0.0 编译及安装 地址:https://github.com/cloudera/hue/releases/t ...
- java 之 原型模式(大话设计模式)
原型模式,在笔者理解看来就是克隆,当我们在创建第一个对象时,已经给对象赋值完毕,此时我们需要一个当前对象的副本,如果没有原型模式,我们会再次创建一个对象,然后后二次赋值,保证两个对象完全一致, 这样我 ...
- 实现基于Haproxy+Keepalived负载均衡高可用架构
1.项目介绍: 上上期我们实现了keepalived主从高可用集群网站架构,随着公司业务的发展,公司负载均衡服务已经实现四层负载均衡,但业务的复杂程度提升,公司要求把mobile手机站点作为单独的服务 ...
- [行业关键词] review code review
意思是 代码评审 或是 代码回顾 代码评审是指在软件开发过程中,通过对源代码进行系统性检查的过程.通常的目的是查找系统缺陷,保证软件总体质量和提高开发者自身水平. Code Review是轻量级 ...