Item1: 考虑使用静态工厂方法代替构造方法
1 什么是静态工厂方法
静态工厂方法不是指设计模式中的工厂方法,而是在类中提供一个静态方法,该类方法返回类的一个实例。
在Java API中有许多这样的例子,如所有的基本对象的包装类都会提供一个valueOf()的方法用于获取该对象的实例:
String str = String.valueOf(1);
Integer integer = Integer.valueOf("1");
Long lon = Long.valueOf("1");
Double dou = Double.valueOf("1");
2 静态工厂方法的好处
2.1 静态工厂方法可以有名字,而构造方法无法命名
编程中起名字很重要,不管是变量名还是方法名,最好能让人见名知意,易于阅读。比如BigInteger.probablePrime方法,返回一个可能为素数的BigInteger。
在当需要提供多个构造方法,而构造方法之间可能仅仅是参数顺序不一样,这样很容易引发错误。而静态工厂方法完全可以避免这种问题
2.2 静态工厂方法不一定要创建一个新对象
这一点在单例模式中有很好的体现。通过将构造方法私有,再提供一个静态方法每次返回同一个实例。
还有一种常见的情况,如果对象的创建成本很高,为了提高效率,不会每次都创建一个新对象,而是使用对象池,将用完的对象放入该池中,当需要一个对象时,通过静态工厂方法返回,方法内部判断对象池中是否有空闲对象,如果没有再创建新对象。
2.3 静态工厂方法可以返回其返回类型的任何子类
首先来看例子:
List<Object> emptyList = Collections.emptyList();
源码:
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
private static class EmptyList<E>
extends AbstractList<E>
implements RandomAccess, Serializable {
private static final long serialVersionUID = 8842843931221139166L;
public Iterator<E> iterator() {
return emptyIterator();
}
public ListIterator<E> listIterator() {
return emptyListIterator();
}
public int size() {return 0;}
public boolean isEmpty() {return true;}
public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
public int hashCode() { return 1; }
}
在源码中可以看到,该方法返回的是一个常量,而该常量是通过创建一个EmptyList对象,它是List的一个子类。
一般而言,对于一个接口Type(如这里的Collection),会提个一个Types的类(如这里的Collections),该类会提供私有构造方法,通过静态工厂方法放回示例,而其中大部分的类都对外隐藏,如上面看到的EmptyList类别设置为private。这样会使整个API更为紧凑。且当下次我要修改EmptyList的实现时,对使用者没有影响。
2.4 返回对象的类可以根据输入参数的不同而不同
2.5 返回对象的类不需要存在
3 缺点
- 当构造方法被私有时,无法被继承(这个点倒是没有很理解,不私有构造方法就可以解决这个问题)
- 程序员无法找到静态工厂方法。主要是指java doc不会把静态公共方法和构造方法放在一起,二是将其和其他普通方法放在一起
4 静态工厂方法常用的名字
- from
- of
- valueOf
- instance/getInstance
- create/newInstance
- getXxxx
- newXxxx

浙公网安备 33010602011771号