考虑静态工厂方法替代构造器
这里的静态工厂方法只是表示一个返回类的实例的静态方法。与设计模式中的不同。
优势1.可以有自己的名字:可读性更高,不像构造器受重载规则的限制(相同参数返回不同对象的需求)。
优势2.可以缓存实例:为重复的调用返回相同对象,避免重复创建对象。
如Boolean.valueOf(boolean) 方法。
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);
}
如果用valueOf创建Boolean对象则可以用==来比较,而不用equals,提升性能。
但是Boolean不能保证只有a==b的时候,才有a.equals(b)为true,即可能a.equals(b)为true,但是a!=b,ab不是同一个对象.
Java的枚举就保证了这一点(只有a==b的时候,才有a.equals(b)为true)
优势3.可以返回所需对象的任何子类:对外开放的api可以隐藏一些实现类,只要提供工厂方法给外部。
如java.util.Collections.unmodifiableList()提供创建不可修改集合的静态方法
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
其中的UnmodifiableRandomAccessList,UnmodifiableList实现类就不用对外提供了,使得API非常简洁。也使得用户不得用具体的实现类的对象来接收这个方法的返回值,不管以后这个具体的类还在不在,增加了还是修改了,对用户都是不可见的。
ps:用户指的使用这个api的代码。
优势4.在使用泛型时可以提供类型推导功能。在java1.7后构造器中就能实现类型推导
1.7之前:List<String> list = new ArrayList<String>();
1.7之前 + 静态工厂方法 后可以:
public static <K> List<K> getArrayList() {
return new ArrayList<K>();
}
List<String> list2 = getArrayList();
1.7:List<String> list = new ArrayList<>();
缺点1. 如果具体实现类不公开,则可能不能被继承扩展(因为其构造函数可能是private,default)。
如上说的UnmodifiableRandomAccessList,对用户不可见,自然也没办法去继承扩展,不过组合优于继承。
解决方法:不用继承,用组合(复合)。
缺点2. 没有办法标识这个方法是普通的静态方法还是一个静态工厂方法。
解决方法:遵循一些常用的静态工厂方法的命名习惯。
如:valueOf,of,getInstance,newInstance,getType,newType.
网友评论