比較 Java 靜態工廠方法與建構函式
阿新 • • 發佈:2022-03-13
1 什麼是靜態工廠方法
Java 靜態工廠方法是在方法前加上 public static,讓這個方法變為公開、靜態的方法。該方法返回該類的一個例項,就好像一個工廠生產出一個產品。所以稱之為靜態工廠方法。在 Boolean.java 中有一個靜態工廠方法示例:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
這裡返回了一個 Boolean 例項。
2 比較靜態工廠方法與建構函式
2.1 名稱
靜態工廠方法可以根據返回例項的性質,定義出具有自描述性質的方法名稱。比如 BigInteger 類定義了一個靜態工廠方法 probablePrime,用於返回一個 BigInteger 型別的素數:
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)); }
但如果是建構函式,那麼只能是類名,比如上例中的 BigInteger。這樣就無法從名稱上判斷返回的 BigInteger 例項到底有什麼性質。
2.2 快取
每次呼叫建構函式都會建立新的物件。如果需要事先建立好物件,並快取起來,以供後期複用。那麼建構函式方式就不能滿足該需求。而靜態工廠方法就可以實現。比如 Boolean.java 中的 valueOf 方法,實際上返回的是實現建立好的靜態屬性 TRUE 與 FALSE:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
下面是事先靜態初始化好的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 子類
擁有建構函式的類,可以被子類所繼承。但只有靜態工廠方法的類卻不行。可以使用類組合方式來解決這一問題。
2.4 總結
比較 | 靜態工廠方法 | 建構函式 |
---|---|---|
名稱 | 可根據情況自定義名稱 | 只能是類名 |
快取 | 可呼叫重複物件 | 每次呼叫都建立新的物件 |
子類 | 不能被子類繼承 | 可以被子類繼承 |
3 靜態工廠方法命名方式
關鍵詞 | 說明 | 入參個數 | 示例 |
---|---|---|---|
from | 型別轉換,A 型別轉換為 B 型別。 | 1 | public static Date from(Instant instant) |
of | 聚合,做合併。 | n | public static <E extends Enum |
instance | 返回例項,可能是新建的,也可能是複用已建立的例項。 | n | public static Object instance(int length) |
create | 返回新建的例項。 | n | public static Object create(int length) |
type | 工廠方法不在要返回的類例項中,type 是要返回的類名稱。 | n | public static |
最後一個示例,方法定義在 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;
}
建議優先考慮使用靜態工廠方法來例項化類。
JoshuaBloch. Effective Java中文版.3版[M]. 機械工業出版社, 2018.p.4-8.