Update 1. 考虑使用静态工厂方法替代构造方法.md

This commit is contained in:
Joe 2018-09-22 21:50:56 +08:00 committed by GitHub
parent 81876e8a39
commit 375f394698
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -21,7 +21,7 @@ public static Boolean valueOf(boolean b) {
因为他们有名字,所以静态工厂方法不会受到上面讨论中的限制。在类中似乎需要具有相同签名的多个构造方法的情况下,用静态工厂方法替换构造方法,并仔细选择名称来突出它们的差异。
**静态工厂方法的第二个优点是,与构造方法不同,它们不需要每次调用时都创建一个新对象。**这允许不可变的类 (条目 17) 使用预先构建的实例,或者在构造时缓存实例,并反复分配它们以避免创建不必要的重复对象。`boolean.valueof(boolean)` 方法说明了这种方法:它从不创建对象。这种技术类似于 `Flyweight` 模式[Gamma95]。如果经常请求等价对象,那么它可以极大地提高性能,特别是如果在创建它们非常昂贵的情况下。
**静态工厂方法的第二个优点是,与构造方法不同,它们不需要每次调用时都创建一个新对象。** 这允许不可变的类 (条目 17) 使用预先构建的实例,或者在构造时缓存实例,并反复分配它们以避免创建不必要的重复对象。`boolean.valueof(boolean)` 方法说明了这种方法:它从不创建对象。这种技术类似于 `Flyweight` 模式[Gamma95]。如果经常请求等价对象,那么它可以极大地提高性能,特别是如果在创建它们非常昂贵的情况下。
静态工厂方法从重复调用返回相同对象的能力允许类保持在任何时候存在的实例的严格控制。这样做的类被称为实例控制( instance-controlled。编写实例控制类的原因有很多。实例控制允许一个类来保证它是一个单例 (3) 项或不可实例化的 (条目 4)。同时,它允许一个不可变的值类 (条目 17) 保证不存在两个相同的实例:当且仅当 `a == b``a.equals(b)`。这是享元模式的基础[Gamma95]。`Enum` 类型 (条目 34) 提供了这个保证。
@ -41,7 +41,7 @@ public static Boolean valueOf(boolean b) {
这两个实现类的存在对于客户是不可见的。 如果 `RegularEnumSet` 不再为小枚举类型提供性能优势,则可以在未来版本中将其淘汰,而不会产生任何不良影响。 同样,未来的版本可能会添加 `EnumSet` 的第三个或第四个实现,如果它证明有利于性能。 客户既不知道也不关心他们从工厂返回的对象的类别; 他们只关心它是 `EnumSet` 的一些子类。
**静态工厂的第 5 个优点是,在编写包含该方法的类时,返回的对象的类不需要存在。**这种灵活的静态工厂方法构成了服务提供者框架的基础,比如 Java 数据库连接 API(JDBC)。服务提供者框架是提供者实现服务的系统,并且系统使得实现对客户端可用,从而将客户端从实现中分离出来。
**静态工厂的第 5 个优点是,在编写包含该方法的类时,返回的对象的类不需要存在。** 这种灵活的静态工厂方法构成了服务提供者框架的基础,比如 Java 数据库连接 API(JDBC)。服务提供者框架是提供者实现服务的系统,并且系统使得实现对客户端可用,从而将客户端从实现中分离出来。
服务提供者框架中有三个基本组:服务接口,它表示实现;提供者注册 API提供者用来注册实现以及服务访问 API客户端使用该 API 获取服务的实例。服务访问 API 允许客户指定选择实现的标准。在缺少这样的标准的情况下API 返回一个默认实现的实例,或者允许客户通过所有可用的实现进行遍历。服务访问 API 是灵活的静态工厂,它构成了服务提供者框架的基础。
@ -49,9 +49,9 @@ public static Boolean valueOf(boolean b) {
服务提供者框架模式有许多变种。 例如,服务访问 API 可以向客户端返回比提供者提供的更丰富的服务接口。 这是桥接模式[Gamma95]。 依赖注入框架(条目 5可以被看作是强大的服务提供者。 从 Java 6 开始,平台包含一个通用的服务提供者框架 `java.util.ServiceLoader`,所以你不需要,一般也不应该自己编写(条目 59。 JDBC 不使用 `ServiceLoader`,因为前者早于后者。
**只提供静态工厂方法的主要限制是,没有公共或受保护构造方法的类不能被子类化。**例如,在 `Collections` 框架中不可能将任何方便实现类子类化。可以说,这可能是因祸得福,因为它鼓励程序员使用组合而不是继承 (条目 18),并且是不可变类型 (条目 17)。
**只提供静态工厂方法的主要限制是,没有公共或受保护构造方法的类不能被子类化。** 例如,在 `Collections` 框架中不可能将任何方便实现类子类化。可以说,这可能是因祸得福,因为它鼓励程序员使用组合而不是继承 (条目 18),并且是不可变类型 (条目 17)。
**静态工厂方法的第二个缺点是,程序员很难找到它们。**它们不像构造方法那样在 API 文档中突出因此很难找出如何实例化一个提供静态工厂方法而不是构造方法的类。Javadoc 工具可能有一天会引起对静态工厂方法的注意。与此同时,可以通过将注意力吸引到类或接口文档中的静态工厂以及遵守通用的命名约定来减少这个问题。下面是一些静态工厂方法的常用名称。以下清单并非完整:
**静态工厂方法的第二个缺点是,程序员很难找到它们。** 它们不像构造方法那样在 API 文档中突出因此很难找出如何实例化一个提供静态工厂方法而不是构造方法的类。Javadoc 工具可能有一天会引起对静态工厂方法的注意。与此同时,可以通过将注意力吸引到类或接口文档中的静态工厂以及遵守通用的命名约定来减少这个问题。下面是一些静态工厂方法的常用名称。以下清单并非完整:
- from——A 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:**Date d = Date.from(instant)**;
- of——一个聚合方法接受多个参数并返回该类型的实例并把他们合并在一起例如**Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING)**;