所有客戶端共享同一單例物件,單例物件內部持有對自身的參考。

整個視窗系統僅一個回收站實例,自行提供存取點,完美契合單例定義。

類別載入時靜態初始化實例,天然執行緒安全,程式碼最簡潔。
public final class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() { return INSTANCE; }
}
優點:無同步開銷、實作簡單、類別載入機制保證安全。缺點:若實例建構耗時且從未使用,會浪費資源(但在 Java 中靜態初始化順序固定,比 C++ 更適合)。

首次呼叫 getInstance() 時才建立實例,需處理多執行緒同步。
public final class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) instance = new LazySingleton();
return instance;
}
}
優點:按需建立。缺點:synchronized 導致每次呼叫皆同步,效能較差;若建構過程耗時,首次併發衝突機率大。

警告:切勿嘗試「雙重檢查鎖定」優化,在 Java 中不可靠,詳見後續章節附錄。
GoF 提出,透過登錄表映射類別名稱到實例,允許子類別繼承並各自成為單例。父類別建構子為 protected,子類別建構子為 public(此為缺點,允許繞過登錄表直接實例化)。
public class RegSingleton {
private static final Map REGISTRY = new HashMap<>();
static {
RegSingleton self = new RegSingleton();
REGISTRY.put(self.getClass().getName(), self);
}
protected RegSingleton() {}
public static RegSingleton getInstance(String name) {
if (name == null) name = RegSingleton.class.getName();
if (!REGISTRY.containsKey(name)) {
try {
REGISTRY.put(name, (RegSingleton) Class.forName(name).newInstance());
} catch (Exception e) { /* handle */ }
}
return REGISTRY.get(name);
}
public String about() { return "Hello, I am RegSingleton."; }
}
子類別範例:
public class RegSingletonChild extends RegSingleton {
public RegSingletonChild() {}
public static RegSingletonChild getInstance() {
return (RegSingletonChild) RegSingleton.getInstance(RegSingletonChild.class.getName());
}
public String about() { return "Hello, I am RegSingletonChild."; }
}
