1 静态工厂方法与构造器
构造器就是类的构造方法,名称与类名相同,只是方法参数不一样;
静态工厂方法就是一个返回类的实例的静态方法,例如Boolean类中的valueOf方法:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
2 静态工厂方法的优势
2.1 优势一:工厂方法名可以自定义,可以定义为有语义的名称
例如,BigInteger类中,构造器BigInteger(int, int, Random)可能返回一个素数,但是对于调用者来说不清晰;如果用名为BigInteger.probablePrime静态工厂方法来表示,显得更清楚。
再举一个JDK的例子:Executors类,在这个类中有newFixedThread、newSingleThreadExecutor、newCachedThreadPool等静态方法,因为它们有“名字”,所有就较为清晰的明白API的含义。
2.2 优势二:不必在每次调用的时候都创建一个新对象
public class Instance() {
private static Instance instance = new Instance();
private Instance(){}
public static Instance getInstance() {
return instance;
}
}
2.3 优势三:可以返回原返回类型的任何子类型的对象
举个JDK中的例子:Collections类
List list = Collections.synchronizedList(new ArrayList())
这个例子就说明了可以返回原返回类型的任何子类型的对象。
2.4 优势四:所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值
结合优势三,意思就是,可以返回不同的子类对象,这些子类对象对客户端来说是不可见的,因此可以灵活地按需返回不同的子类对象。
2.5 优势五:方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在
TODO
3 静态工厂方法的缺点
3.1 缺点一:类如果不含公有的或者受保护的构造器,就不能被子类化
例如,要想将Collection Framework中的任何便利的实现类子类化,这是不可能的。但是这样也许会因祸得福,因为它鼓励程序员使用复合(composition),而不是继承,这正是不可变类型所需要的。
3.2 缺点二:查找API比较麻烦
在API文档中,静态工厂方法没有像构造器那样在API文档中明确标识出来,因此,对于提供了静态工厂方法而不是构造器的类来说,要想查明如何实例化一个类是非常困难的。
静态工厂方法的一些惯用名称:
3.2.1 from——类型转换方法
只有单个参数,返回该类型的一个相对应的实例,例如
Date d = Date.from(instant);
3.2.2 of——聚合方法
带有多个参数,返回该类型的一个实例,把它们合并起来,例如
Set<Rank> faceCards = EnumSet.of(JACK,QUEEN,KING);
3.2.3 valueOf——比from和of更繁琐的一种替代方法
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
3.2.4 instance或者getInstance
返回的实例时通过方法的(如有)参数来描述的,但是不能说与参数具有同样的值,例如
StackWalker luke = StackWalker.getInstance(options);
3.2.5 create或者newInstance
像instance或者getInstance一样,区别在于每次调用都返回一个新的实例,例如:
Object newArray = Array.newInstance(classObject,arrayLen);
3.2.6 getType
像getInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型,例如:
FileStore fs = Files.getFileStore(path);
3.2.7 newType
像newInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型,例如:
BufferedReader br = Files.newBufferedReader(path);
3.2.8 Type
getType
和newType
的简版,例如
List<Complaint> litany = Collections.list(LegacyLitany);