確保類別在 JVM 中僅有一個實例,並提供全域存取點。典型應用:資料庫連線池、Socket 連線管理、設定檔載入器、JDK Collections.singleton() 內部實作。
uniqueInstance:私有靜態欄位,持有唯一實例參考。getInstance():公有靜態方法,延遲初始化並回傳實例。private:防止外部直接 new。public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) instance = new Singleton();
return instance;
}
}
缺點:多執行緒環境下可能產生多個實例 (Race Condition)。
class SingletonException extends RuntimeException {
SingletonException(String msg) { super(msg); }
}
public class Singleton {
private static boolean instantiated = false;
public Singleton() {
if (instantiated) throw new SingletonException("Only one instance allowed");
instantiated = true;
}
}
缺點:客戶端需自行捕獲異常,API 不直覺;無法延遲初始化 (載入類別即實例化)。
public class SingletonRegistry {
private static Map registry = new Hashtable<>();
public static synchronized void register(String key, Object instance) {
if (!registry.containsKey(key)) registry.put(key, instance);
}
public static synchronized Object getInstance(String key) {
return registry.get(key);
}
}
// 使用
SingletonRegistry.register("DBPool", new DBConnectionPool());
DBConnectionPool pool = (DBConnectionPool) SingletonRegistry.getInstance("DBPool");
優點:集中管理不同類型的單例、支援動態註冊、易於單元測試替換。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) instance = new Singleton();
}
}
return instance;
}
}
public class Singleton {
private Singleton() {}
private static class Holder { static final Singleton INSTANCE = new Singleton(); }
public static Singleton getInstance() { return Holder.INSTANCE; }
}
public enum Singleton { INSTANCE; }
| 寫法 | 執行緒安全 | 延遲初始化 | 防序列化破壞 | 推薦度 |
|---|---|---|---|---|
| 懶漢式 (無同步) | ❌ | ✅ | ❌ | ⭐ |
| 餓漢式 (靜態最終欄位) | ✅ | ❌ | ❌ | ⭐⭐ |
| DCL + volatile | ✅ | ✅ | ❌ | ⭐⭐⭐ |
| 靜態內部類 | ✅ | ✅ | ❌ | ⭐⭐⭐⭐ |
| Enum | ✅ | ✅ | ✅ | ⭐⭐⭐⭐⭐ |
實務上優先考慮 Enum 或 靜態內部類;需管理多型單例時採用 Registry。