对于类而言,为了让客户端获取类的一个实例对象,最常用的方法就是提供一个公有的构造器,但是还有一种方法,使用公有的静态工厂方法(注意与设计模式区分),该方法可以返回类的实例对象。
一、静态工厂方法与构造器相比优势在于:
(1)静态工厂方法有名称。事实上构造器输入的参数本身并没有确切的描述正在返回的对象,此时一个适当名称的静态工厂方法更容易让开发者理解。此外,一个类只能有一个输入完全相同(参数数量、顺序及类型)的构造器,当为了使用两个传入参数一致的构造器时,开发人员会通过提供两个构造器,它们的参数列表在顺序上有所不同,进而实现上述需求,但是这种操作经常会调用出错,因为名称都是一样的,只是传入参数的顺序不一致。静态工厂方法有名称,因此不会受到上述的限制,当以一个类需要多个带有相同参数的构造器时,可以使用静态工厂方法代替构造器,此时只需要慎重对方法进行命名即可。
(2)静态工厂方法不必每次调用时都创建一个新的对象。如果程序经常请求创建相同的对象,并且创建对象的代价很高,使用箭头工厂方法可以极大的提升性能。静态工厂方法能够为重复调用返回相同的对象,这样有助于类总能严格控制在某个时刻哪些实例应该存在。这样设计可以确保该类是一个单例或者不可实例化,它还是的不可变类确保不会存在两个相同的实例。
(3)可以返回原返回类型的任何子类型的对象。这种设计的灵活性在于返回对象时,不会使对象的类成为公有化的类,这种设计适用于基于接口的框架,接口为静态方法提供了自然返回类型,但是接口中不能有静态方法,因此该接口的静态方法就会封装在一个类似名称的不可实例化的类中,例如Type的静态方法封装在Types的不可实例化队形的类中。
目前,在实现一个对象时,被返回的对象是由相关的接口精确指定的,使用静态工厂方法时,要求客户端通过接口来引用被返回的对象,而不是通过它的实现类来引用(面向接口编程)。
公有的静态工厂方法返回的对象的类不仅可以是非公有的,而且该类还可以随着每次调用而发生变化。只要是已声明的返回类型的子类型即可。
(4)在创建参数化类型的实例的时候,使代码变得更简洁。
例如:实例化一个map对象
Map<String,List<String>> m = new HashMap<String,List<String>>;
可以使用如下方法代替:
加入HashMap中提供了如下静态方法,
public static <K,V> HashMap<K,V> newInstance(){
return new HashMap<K,V>();
}
则实例化对象时,可以使用如下方法:
Map<String,List<String>> m = HashMap.newInstance();
二、静态工厂方法与构造器相比缺陷在于:
(1)类中必须含有公有或者受保护的构造器,否则不能被子类化。
(2)静态工厂方法与静态方法在实质上没有任何区别。