对于一个类,要获取它的一个实例,通常的做法是提供一个公用的构造函数,然而还有另一种方法,我们称之为静态工厂方法,实质上也就是一个简单的静态方法,它返回一个类的实例。其实,静态工厂方法获取对象实例,我们并不陌生,我们来看看API中的一个实例:
首先注意 ,静态工厂方法与设计模式中的工厂方法模式是不同的。下面是一个Boolean的中的实例
public final class Boolean implements java.io.Serializable, Comparable<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); }}
类可以为其客户端提供静态工厂方法,而不是公共构造方法。但是既有优点,也有缺点。
第一个优点是,不像构造方法,它们是有名字的。 比如返回一个可能为素数的BigInteger的构造方法BigInteger(int, int, Random),可以被更好的命名为BigInteger.probablePrime的静态工厂方法。提高可读性。
第二个优点是,与构造方法不同,不需要每次都创建一个新对象,这个看看上方Boolean的代码示例就会明白
第三个优点是, 与构造方法不同,它们可以返回任意类型的任何子类型的对象
第四个优点是,返回的对象的类可以根据输入参数的不同而不同
EnumSet 类(条目 36)没有公共构造方法,只有静态工厂。
/** * Creates an empty enum set with the specified element type. * * @param <E> The class of the elements in the set * @param elementType the class object of the element type for this enum * set * @return An empty enum set of the specified type. * @throws NullPointerException if <tt>elementType</tt> is null */ public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { Enum<?>[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); }
第五个优点是,在编写包含该方法的类时,返回的对象的类不需要存在这种灵活的静态工厂方法构成了服务提供者框架的基础,比如 Java 数据库连接 API(JDBC)。服务提供者框架是提供者实现服务的系统,并且系统使得实现对客户端可用,从而将客户端从实现中分离出来。
只提供静态工厂方法的主要限制是,没有公共或受保护方法的类不能被子类化
第二个缺点是,程序员很难找到它们,哈哈,就问你怕不怕
以下是一些静态工厂方法的常用名称:
from——A 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:Date d = Date.from(instant);
of——一个聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf——from 和 to 更为详细的替代 方式,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE); instance 或 getinstance——返回一个由其参数 (如果有的话) 描述的实例,但不能说它具有相同的值,例如:StackWalker luke = StackWalker.getInstance(options);
create 或 newInstance——与 instance 或 getInstance 类似,除了该方法保证每个调用返回一个新的实例,例如:Object newArray = Array.newInstance(classObject, arrayLen);
getType——与 getInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:FileStore fs = Files.getFileStore(path);
newType——与 newInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例如:BuweredReader br = Files.newBuweredReader(path);
type—— getType 和 newType 简洁的替代方式,例如:List litany = Collections.list(legacyLitany);
总之,静态工厂方法和公共构造方法都有它们的用途,并且了解它们的相对优点是值得的。通常,静态工厂更可取,因此避免在没有考虑静态工厂的情况下提供公共构造方法。
ps:如果有微信读书的书友,可以来微信读书群传送门找组织。