1 什么是靜態(tài)工廠方法
Java 靜態(tài)工廠方法是在方法前加上 public static,讓這個方法變?yōu)楣_、靜態(tài)的方法。該方法返回該類的一個實例,就好像一個工廠生產(chǎn)出一個產(chǎn)品。所以稱之為靜態(tài)工廠方法。在 Boolean.java 中有一個靜態(tài)工廠方法示例:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
這里返回了一個 Boolean 實例。
2 比較靜態(tài)工廠方法與構(gòu)造函數(shù)
2.1 名稱
靜態(tài)工廠方法可以根據(jù)返回實例的性質(zhì),定義出具有自描述性質(zhì)的方法名稱。比如 BigInteger 類定義了一個靜態(tài)工廠方法 probablePrime,用于返回一個 BigInteger 類型的素數(shù):
public static BigInteger probablePrime(int bitLength, Random rnd) {
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
return (bitLength < SMALL_PRIME_THRESHOLD ?
smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
}
但如果是構(gòu)造函數(shù),那么只能是類名,比如上例中的 BigInteger。這樣就無法從名稱上判斷返回的 BigInteger 實例到底有什么性質(zhì)。
2.2 緩存
每次調(diào)用構(gòu)造函數(shù)都會創(chuàng)建新的對象。如果需要事先創(chuàng)建好對象,并緩存起來,以供后期復(fù)用。那么構(gòu)造函數(shù)方式就不能滿足該需求。而靜態(tài)工廠方法就可以實現(xiàn)。比如 Boolean.java 中的 valueOf 方法,實際上返回的是實現(xiàn)創(chuàng)建好的靜態(tài)屬性 TRUE 與 FALSE:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
下面是事先靜態(tài)初始化好的TRUE 與 FALSE:
/**
* 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);
2.3 子類
擁有構(gòu)造函數(shù)的類,可以被子類所繼承。但只有靜態(tài)工廠方法的類卻不行??梢允褂妙惤M合方式來解決這一問題。
2.4 總結(jié)
| 比較 | 靜態(tài)工廠方法 | 構(gòu)造函數(shù) |
|---|---|---|
| 名稱 | 可根據(jù)情況自定義名稱 | 只能是類名 |
| 緩存 | 可調(diào)用重復(fù)對象 | 每次調(diào)用都創(chuàng)建新的對象 |
| 子類 | 不能被子類繼承 | 可以被子類繼承 |
3 靜態(tài)工廠方法命名方式
| 關(guān)鍵詞 | 說明 | 入?yún)€數(shù) | 示例 |
|---|---|---|---|
| from | 類型轉(zhuǎn)換,A 類型轉(zhuǎn)換為 B 類型。 | 1 | public static Date from(Instant instant) |
| of | 聚合,做合并。 | n | public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) |
| instance | 返回實例,可能是新建的,也可能是復(fù)用已創(chuàng)建的實例。 | n | public static Object instance(int length) |
| create | 返回新建的實例。 | n | public static Object create(int length) |
| type | 工廠方法不在要返回的類實例中,type 是要返回的類名稱。 | n | public static <T> ArrayList<T> list(Enumeration<T> e) |
最后一個示例,方法定義在 Collections 中,要返回的是 ArrayList 實例,所以被命名為 list。
public static <T> ArrayList<T> list(Enumeration<T> e) {
ArrayList<T> l = new ArrayList<>();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
建議優(yōu)先考慮使用靜態(tài)工廠方法來實例化類。
JoshuaBloch. Effective Java中文版.3版[M]. 機械工業(yè)出版社, 2018.p.4-8.