Effective Java 条款1

读书笔记

2019年11月17日发布📑

ITEM 1: Consider static factory methods instead of constructors

属于 “创建和销毁对象” 那章。静态工厂方法跟“四人帮”设计模式里面的工厂方法模式是不同的。

静态工厂方法的好处

  1. 有名称,容易读。

  2. 静态工厂方法不一定每次都创建新实例。有点类似享元模式(Flyweight pattern)。如果创建对象代价比较大,使用静态工厂方法可以提高性能。这种类被称为实例受控instance-controlled)类。可以确保单例singleton)或不被实例化。还有让值不可变类(immutable value class)保存没有两个相等的实例存在。

  3. 可返回任意子类的对象。

  4. 静态工厂方法返回的对象可以因调用参数不同而不同。

  5. 返回的对象可以先不存在,这就是 service provider framework 的基础,例如 Java Database Connectivity API (JDBC).

    服务提供者框架的三个主要组件:服务接口(service interface),代表实现。服务提供者注册接口(provider registration API),用于注册服务的实现。服务访问接口(service access API),客户端用来获取服务实例的方式。以 JDBC 为例子,Connection 就是服务接口, DriverManager.registerDriver 是服务提供者注册接口, DriverManager.getConnection 是服务访问接口,然后 Driver 是服务提供者接口。

静态工厂方法的缺点

  1. 只提供私有静态工厂方法(没有 publicprotected 构造器)的类不能被继承(派生),不过有时候是好事,因为鼓励使用组合而不是继承。
  2. 比较难找,因为不想构造器那样出现在 java doc。

一些静态工厂方法的例子:

  • from —— 一种类型转换方法,取一个参数并返回此类型对应的实例,例如:

    Data d = Date.from(instant);

  • of —— 一种聚集方法,取多个参数,返回此类型的实例,整合了这些参数的值,例如:

    Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);

  • valueOf —— 更详尽版本的 of ,例如:

    BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

  • instancegetInstance —— 返回参数描述的实例,但不一定得到同样的值。例如:

    StackWalker luke = StackWalker.getInstance(options);

  • createnewInstance —— 像前一个,但是保证每次都返回新实例。例如:

    Object newArray = Array.newInstance(classObject, arrayLen);

  • getType —— 像 getInstance 但是在不同类里面,Type 是静态工厂方法返回的对象类型,例如:

    FileStore fs = Files.getFileStore(path);

  • newType —— 像 newInstance 但是在不同类里面,Type 是静态工厂方法返回的对象类型,例如:

    BufferedReader br = Files.newBufferedReader(path);

  • type —— getTypenewType 的更精简替换,例如:

    List<Complaint> litany = Collections.list(legacyLitany);

总结

通常使用静态工厂方法更好,所以可以考虑一下,而不是只想到公有构造器。