对于类,获取类实例的方式除了通过公有构造器的方式。还有一种方式,就是可以提供一个公有的静态工厂方法,只是一个返回类实例的静态方法 ,比如Boolean类的简单示例:
public static Boolean valueOf(boolean b){
return b ? Boolean.TRUE : Boolean:FALSE;
}
凡事都是有利有弊的,静态工厂方法代替构造器去创建类实例也是需要考虑应用场景的。
静态工厂方法的优点
- 静态方法名称是自由的,可以描述构造行为。一些类需要通过不同的参数来执行不同的功能。虽然构造器也可以通过使用不同参数个数以及顺序的方式来实现创建不同规格的实例,但是还是不能做到见名知意,很容易就会发生使用错误
// 可能举得这个例子举得不是很恰当
public class IntExample {
private Integer num;
public IntExample(Integer num){
}
// 第一个静态工厂方法
public static IntExample getIntExampleForOne(){
return new IntExample(1);
}
// 第二个静态工厂方法
public static IntExample getIntExampleForTwo(){
return new IntExample(2);
}
}
- 不必在每次调用静态工厂方法的时候都创建一个新对象,而构造方法是必须创建出一个新的实例 ,静态工厂的这种方式可以将构建好的实例缓存起来,进行重复使用,避免创建没必要的重复对象。Boolean.valueOf(boolean)就说明了这项技术,类似于享元模式。
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
- 静态工厂方法可以返回原返回类型的任何子类对象,有了更大的灵活性
- 所返回的对象的类可以随着每次调用而发生变化,取决于静态工厂方法的参数值
- 方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在。(这句不是很理解,原文中的内容)
静态工厂方法的缺点
-
静态工厂方法的主要缺点在于,类如果不含共有或者受保护的构造器,就不能被子类实例化
-
很难被发现,在API文档中,没有像构造器那样在API文档中明确标识出来。通过在类或接口注释中关注静态工厂,并遵守标准的命名习惯,可以弥补这一劣势,静态工厂方法的一些惯用名称如下: From - 类型转换方法,如
Date d = Date.from(instant);Of - 聚合方法,带有多个参数,如Set<Rank> faceCards = EnumSet.of(JACK,QUEEN,KING);