確保一個類別在全域僅有一個實例,並提供全域存取點。適用於日誌記錄器、配置管理器、資料庫連線池、執行緒池等場景。
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {} // 私有建構子
public static Singleton getInstance() { return INSTANCE; }
}
public final 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;
}
}
volatile 禁止指令重排,確保其他執行緒看到完全初始化的物件。readResolve() 返回唯一實例。public enum Singleton { INSTANCE; } 天然防序列化/反射破壞,簡潔安全。由一個工廠類別根據傳入參數決定建立哪個具體產品類別,封裝物件建立細節,客戶端僅面向抽象產品介面。
interface Shape { void draw(); }
class Circle implements Shape { public void draw() { System.out.println("畫圓"); } }
class Rectangle implements Shape { public void draw() { System.out.println("畫矩形"); } }
class ShapeFactory {
public static Shape create(String type) {
switch (type.toLowerCase()) {
case "circle": return new Circle();
case "rect": return new Rectangle();
default: throw new IllegalArgumentException("未知形狀: " + type);
}
}
}
// 客戶端
Shape s = ShapeFactory.create("circle");
s.draw(); // 輸出:畫圓
| 優點 | 缺點 |
|---|---|
| 客戶端解耦具體類別 | 新增產品需修改工廠類,違反開閉原則 |
| 集中管理建立邏輯 | 工廠職責過重,單點故障風險 |
當產品族固定、變動少時適用;頻繁擴展產品類型請改用工廠方法模式或抽象工廠模式。
| 模式 | 核心解決問題 | 關鍵實現點 | 典型應用 |
|---|---|---|---|
| 單例 | 全域唯一實例 | 私有建構子 + 靜態工廠方法 + volatile/DCL/枚舉 | Logger、Config、ConnectionPool |
| 簡單工廠 | 封裝物件建立 | 靜態工廠方法 + switch/if 判斷類型 | 圖形、資料庫驅動、解析器 |