第一章 润色 (#53)

This commit is contained in:
Fudeveloper 2020-03-31 22:51:05 -05:00 committed by GitHub
parent c646674789
commit 3816ddcb5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,7 @@
# 1. 考虑使用静态工厂方法替代构造方法
  一个类允许客户端获取其实例的传统方式是提供一个公共构造方法。 其实还有另一种技术应该成为每个程序员工具箱的一部分。 一个类可以提供一个公共静态工厂方法,它只是一个返回类实例的静态方法。 下面是一个 `Boolean` 简单的例子(`boolean` 基本类型的包装类)。 此方法将 `boolean` 基本类型转换为 `Boolean` 对象引用:
  一个类允许客户端获取其实例的传统方式是提供一个公共构造方法。 其实还有另一种技术应该成为每个程序员工具箱的一部分。 一个类可以提供一个简单的、只返回该类实例的公共静态工厂方法。 下面是一个 `Boolean` 简单的例子( 基本类型`boolean`的包装类)。 此方法将基本类型`boolean`转换为 `Boolean` 对象引用:
```java
public static Boolean valueOf(boolean b) {
@ -11,26 +11,26 @@ public static Boolean valueOf(boolean b) {
  注意,静态工厂方法与设计模式中的工厂方法模式不同[Gamma95]。本条目中描述的静态工厂方法在设计模式中没有直接的等价。
  类可以为其客户端提供静态工厂方法,而不是公共构造方法。提供静态工厂方法而不是公共构造方法有优点也有缺点。
  类可以为其客户端提供静态工厂方法,而不是公共构造方法。提供静态工厂方法来代替提供公共构造方法这种方式,有优点也有缺点。
  **静态工厂方法的一个优点是,与构造方法不同,它们是有名字的。** 如果构造方法的参数本身并不描述被返回的对象,则具有精心选择名称的静态工厂更易于使用,并且生成的客户端代码更易于阅读。 例如,返回一个可能为素数的 `BigInteger` 的构造方法 `BigInteger(intintRandom)` 可以更好地表示为名为 `BigInteger.probablePrime` 的静态工厂方法。 (这个方法是在 Java 1.4 中添加的。)
  一个类只能有一个给定签名的构造方法。 程序员知道通过提供两个构造方法来解决这个限制,这两个构造方法的参数列表只有它们的参数类型的顺序不同。 这是一个非常糟糕的主意。 这样的 API 用户将永远不会记得哪个构造方法是哪个,最终会错误地调用。 阅读使用这些构造方法的代码的人只有在参考类文档的情况下才知道代码的作用。
  一个类只能有一个给定签名的构造方法。 程序员知道通过提供两个仅仅在参数类型的顺序不同的构造方法来解决这个限制。 这是一个非常糟糕的主意。 对于这样的 API 用户将永远不会记得哪个构造方法是哪个,最终会错误地调用。 阅读使用这些构造方法的代码的人只有在参考类文档的情况下才知道代码的作用。
  因为他们有名字,所以静态工厂方法不会受到上面讨论中的限制。在类中似乎需要具有相同签名的多个构造方法的情况下,用静态工厂方法替换构造方法,并仔细选择名称来突出它们的差异。
  因为静态工厂方法有名字,所以它们不会受到上述限制。在类中似乎需要具有相同签名的多个构造方法的情况下,用静态工厂方法替换构造方法,并仔细选择名称来突出它们的差异。
  **静态工厂方法的第二个优点是,与构造方法不同,它们不需要每次调用时都创建一个新对象。** 这允许不可变类 (详见第 17 条)使用预先构建的实例,或者在构造时缓存实例,并反复分配它们以避免创建不必要的重复对象。`Boolean.valueof(boolean)` 方法说明了这种方法:它从不创建对象。这种技术类似于 `Flyweight` 模式[Gamma95]。如果经常请求等价对象,那么它可以极大地提高性能,特别是在创建它们的代价非常昂贵的情况下。
  静态工厂方法重复调用返回相同实例这个特点可以让类在任何时候都能对实例保持严格的控制。这样做的类被称为实例控制类( instance-controlled。有很多理由足以让我们去我们编写实例控制类。实例控制可以保证一个类是单例 的(详见第 3 条) 或不可实例化的 (详见第 4 条)。同时,它允许一个不可变的值类 (详见第 17 条) 保证不存在两个相等但不相同的实例,也就是说当且仅当 `a == b` 时才有 `a.equals(b)`。这是`Flyweight`模式的基础[Gamma95]。`Enum` 类型 (详见第 34 条)可以做到这点。
  静态工厂方法重复调用时,返回相同实例这个特点可以让类在任何时候都能对实例保持严格的控制。这样做的类被称为实例控制类( instance-controlled。有很多理由足以让我们去我们编写实例控制类。实例控制可以保证一个类是单例 的(详见第 3 条) 或不可实例化的 (详见第 4 条)。同时,它允许一个不可变的值类 (详见第 17 条) 保证不存在两个相等但不相同的实例,也就是说当且仅当 `a == b` 时才有 `a.equals(b)`。这是`Flyweight`模式的基础[Gamma95]。`Enum` 类型 (详见第 34 条)可以做到这点。
  **静态工厂方法的第三个优点是,与构造方法不同,它们可以返回其返回类型的任何子类型的对象。** 这为你在选择返回对象的类时提供了很大的灵活性。
  **静态工厂方法的第三个优点是,与构造方法不同,它们可以返回其返回类型的任何子类型的对象。** 这为你在选择返回对象的类提供了很大的灵活性。
  这种灵活性的一个应用是 API 可以返回对象而不需要公开它的类。 以这种方式隐藏实现类会使 API 非常紧凑。 这种技术适用于基于接口的框架(详见第 20 条),其中接口为静态工厂方法提供自然返回类型。
  这种灵活性的一个应用是 API 可以返回对象而不需要公开它的类。 以这种方式隐藏实现类会使 API 非常紧凑。 这种技术适用于基于接口的框架(详见第 20 条),其中接口为静态工厂方法提供自然返回类型。
  在 Java 8 之前,接口不能有静态方法。根据约定,一个名为 `Type` 的接口的静态工厂方法被放入一个不可实例化的伙伴类companion class详见第 4 条)`Types` 类中。例如Java 集合框架有 45 个接口的实用工具实现,提供不可修改的集合、同步集合等等。几乎所有这些实现都是通过静态工厂方法在一个不可实例化的类 (`java .util. collections`) 中返回的。返回对象的类都隐藏的。
  在 Java 8 之前,接口不能有静态方法。根据约定,一个名为 `Types` 的接口的静态工厂方法被放入一个不可实例化的伙伴类companion class详见第 4 条)`Types` 类中。例如Java 集合框架有 45 个接口的实用工具实现,提供不可修改的集合、同步集合等等。几乎所有这些实现都是通过静态工厂方法在一个不可实例化的类 (`java.util.collections`) 中返回的。返回对象的类都隐藏的。
  `Collections` 框架 API 的规模要比它之前返回的 45 个单独的公共类要小得多,每个类在集合框架中都有一个便利的实现。不仅是 API 的大部分减少了,还包括概念上的权重:程序员要想使用 API必须掌握的概念的数量和难度。程序员知道返回的对象恰好有其接口指定的 API因此不需要为实现类读阅读额外的类文档。此外使用这种静态工厂方法需要客户端通过接口而不是实现类来引用返回的对象,这通常是良好的实践(详见第 64 条)。
  `Collections` 框架 API 的规模要比它之前返回的 45 个单独的公共类要小得多,每个类在集合框架中都有一个便利的实现。不仅精简了API还减少了程序员为了使用 API而掌握的概念的数量和难度。程序员知道返回的对象恰好有其接口指定的 API因此不需要为实现类读阅读额外的类文档。此外使用这种静态工厂方法,需要客户端通过接口替代实现类,来引用返回的对象,这通常是良好的实践(详见第 64 条)。
  从 Java 8 开始,接口不能包含静态方法的限制被取消了,所以通常没有理由为接口提供一个不可实例化的伴随类。 很多公开的静态成员应该放在这个接口本身。 但是,请注意,将这些静态方法的大部分实现代码放在单独的包私有类中仍然是必要的。 这是因为 Java 8 要求所有接口的静态成员都是公共的。 Java 9 允许私有静态方法,但静态字段和静态成员类仍然需要公开。
@ -61,7 +61,7 @@ public static Boolean valueOf(boolean b) {
- newType —— 与 newInstance 类似,但是在工厂方法处于不同的类中的时候使用。**newType**中的 **Type** 是工厂方法返回的对象类型,例如:**BufferedReader br = Files.newBufferedReader(path)**;
- type —— getType 和 newType 简洁的替代方式,例如:**List\<Complaint\> litany = Collections.list(legacyLitany)**;
  总之,静态工厂方法和公共构造方法都有它们的用途,并且了解它们的相对优点是值得的。通常,静态工厂更可取,因此避免在没有考虑静态工厂的情况下直接选择使用公共构造方法。
  总之,静态工厂方法和公共构造方法都有它们的用途,并且了解它们的相对优点是值得的。通常,静态工厂更可取,因此避免在没有考虑静态工厂的情况下直接选择使用或提供公共构造方法。