Effective-Java-1考虑用静态工厂方法代替构造器
静态工厂方法与构造器不同的优点
它们有名称 (静态方法)
例:构造器 BigInteger(int, int, Random) 返回的 BigInteger 可能为素数,如果用名为 BigInteger.probablePrime 的静态工厂方法来表示,显然更为清楚 (1.4的发行版本中最终增加了这个方法)
不必每次调用时都创建一个新对象 (可以将构建好的实例进行缓存并重复利用)
Boolean.valueOf(boolean) 从来不创建对象。这种方法类似于 Flyweight模式(享元模式)。如果程序经常创建相同的对象,并且创建对象的代价高,这种技术将会极大的提升性能。
可以返回原返回类型的任何子类型对象 (可以返回隐藏类的实例,将实现类隐藏将使得API十分简洁)
创建参数化类型(泛型)实例的时候,使代码变得更加简洁 (类型推导 type inference)
1
2
3
4
5
6
7
8// 调用参数化构造器时,指明类型
Map<String, List<String>> map = new HashMap<String, List<String>>();
// 假如在 HashMap 中提供静态工厂
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
// 创建实例将会变简洁
Map<String, List<String>> map = HashMap.newInstance();
静态工厂方法的缺点
类如果不含公有的或者受保护的构造器,就不能被子类化
与其他的静态方法实际上没有任何区别
在API文档中,静态工厂方法不会像构造器一样被单独列出并标识,对于仅提供静态工厂方法的类而言,想查到如何实例化该类是比较麻烦的。
静态工厂方法的一些惯用名称如下:
- valueOf
- of
- getInstance
- newInstance
- getType
- newType
静态工厂方法和共有构造器各有用处,一般情况下静态工厂更加合适,优先提供静态工厂,而不是共有构造器
个人总结: 静态工厂方法是对获取对象的一种封装(封装为静态方法),具体实现可隐藏于其中,具有更高的灵活性