用静态工厂方法代替构造方法
本文为作者学习 Effective Java 一书的学习笔记第一篇,会持续更新,见专栏 Effective Java
提供公有的静态工厂方法,返回类的实例。
例如:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
优势
1. 各有名称。
具有适当名称的静态工厂会更容易使用和阅读,通过名称突出不同方法之间的区别。如
BigInteger.probablePrime()
2. 可以不必每次调用时都创建新的对象
可以使用预先创建好的实例,如单例模式、享元模式,上面的 Boolean.valueOf
就使用了这个技术
3. 可以返回子类型的对象
同时还可以通过API返回对象,同时不会使对象的类变成公有的。例如 java.util.Collections
中导出的对象,如 synchronizedList() 返回了类的内部定义的非公有类的对象
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E>
static class SynchronizedRandomAccessList<E>
extends SynchronizedList<E>
implements RandomAccess
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
4. 返回的对象的类可以随着每次调用的传参而发生变化
只有是已声明的类型的子类型,都可以返回。例如 EnumSet
没有公有的构造方法,只有静态工厂方法,具体返回取决于底层枚举类型的大小,若元素有64个或更少,则返回 RegularEnumSet
实例,否则返回 JumboEnumSet
。
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType)
public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType)t;
public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s)
public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c)
public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s)
5. 方法返回的对象所属的类,在编写包含该静态工厂方法的类时,可以不存在
一个典型的例子是 JDBC API,被称为 服务提供者框架(Service Provider Framework) 。
该框架分为四个组件
- 服务接口(Service Interface):Connection
- 提供者注册API(Provider Registration API):DriverManager.registerDriver
- 提供者接口(Service Provider Interface):Driver
- 服务访问API(Service Access API):DriverManager.getConnection
劣势
1. 类如果不含有公有的或受保护的构造方法,就不能被子类化
2. 程序员很难发现并使用。
在API文档中,没有像构造方法一样明确标识出来
常用的静态方法名称
-
from —— 类型转换方法
-
of —— 聚合方法
-
valueOf
-
instance 或者 getInstance
-
create 或者 newInstance
-
getType
-
newType
-
type