類別提供一個 public static 方法回傳該類別(或子類別)實例,而非直接使用 public 建構子。經典範例:Boolean.valueOf(boolean)、Collections.singletonList()。
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE; // 回傳預先建立的常量實例
}
BigInteger.probablePrime() 比 new BigInteger(...) 更能表達意圖。Boolean、Integer.valueOf(-128~127))、單例、享元模式。EnumSet.noneOf() 回傳 RegularEnumSet 或 JumboEnumSet)。new HashMap<String,List<String>>>() 繁瑣,工廠方法可推導型參:HashMap.newInstance()(或 Guava Maps.newHashMap())。public/protected 建構子,子類別無法呼叫 super(),導致無法繼承。(解法:改用非 final 類別 + protected 建構子 + 文檔規範)| 名稱 | 用途 | 範例 |
|---|---|---|
valueOf | 型別轉換、回傳等值實例 | String.valueOf(int), BigInteger.valueOf(long) |
of | 簡潔工廠,常用於集合、Optional | List.of(), Optional.of() |
getInstance | 單例模式 | Calendar.getInstance() |
newInstance | 每次建立新實例 | Array.newInstance() |
getType | 回傳不同類別的工廠(參數化型別) | FileStore.getFileStore() |
newType | 建立新實例,強調「新」 | BufferedReader.newBufferedReader() |
public final class ConnectionConfig {
private final String url;
private final int timeout;
private static final Map<String, ConnectionConfig> CACHE = new ConcurrentHashMap<>();
private ConnectionConfig(String url, int timeout) {
this.url = url; this.timeout = timeout;
}
// 靜態工廠:驗證參數、快取重用
public static ConnectionConfig of(String url, int timeout) {
if (url == null || url.isBlank()) throw new IllegalArgumentException("URL 不能為空");
if (timeout <= 0) throw new IllegalArgumentException("逾時需為正數");
String key = url + "#" + timeout;
return CACHE.computeIfAbsent(key, k -> new ConnectionConfig(url, timeout));
}
// 公開唯讀屬性
public String getUrl() { return url; }
public int getTimeout() { return timeout; }
}
靜態工廠方法提供更豐富的語意、實例控制與彈性,是 API 設計的利器。只要注意「不可繼承」與「可發現性」兩大缺點,配合命名慣例與完整文檔,即可在恰當場合發揮最大效用。