首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 設計模式深度解析:單例模式

     編輯:Java 相關知識

什麼是單例模式?

單例模式屬於創建型模式,定義為:確保一個類只有一個實例,且自行實例化並向整個系統提供這個實例。它是 23 種設計模式中最簡單、也是實務中最常用的一種。

核心三要素

單例模式類圖

  1. private 建構子:防止外部 new。
  2. private static 靜態引用:指向唯一實例。
  3. public static 獲取方法:全局訪問入口。

兩種經典實現

餓漢式(類載入即實例化)

public class Singleton {
    private static Singleton singleton = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() { return singleton; }
}

優點:線程安全、實現簡單。缺點:類載入即佔用記憶體,即使未使用。

懶漢式(首次調用才實例化)

public class Singleton {
    private static Singleton singleton;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (singleton == null) { singleton = new Singleton(); }
        return singleton;
    }
}

優點:延遲載入。缺點:synchronized 影響性能(可用雙重檢查鎖優化,但需 volatile 修飾)。

優點與適用場景

  • 記憶體中僅一個對象,節省空間。
  • 避免頻繁創建/銷毀,提升性能。
  • 避免共享資源多重佔用(如資料庫連接、配置管理)。
  • 全局訪問便利。

典型場景:頻繁實例化銷毀的對象、創建耗時/耗資源的工具類、有狀態的工具類、頻繁訪問 DB/文件的對象。

五大避坑指南

  1. 反射破壞:Constructor.setAccessible(true) 可繞過 private 建構子創建新實例。對策:建構子中檢測實例是否存在,拋異常阻止。
  2. 序列化/反序列化:會產生新對象。對策:實現 readResolve() 返回現有實例。
  3. 類加載器隔離:多類加載器環境下會產生多個單例。
  4. 手動斷開引用:切勿將靜態引用設為 null。
  5. 多線程共享資源:單例內部狀態操作需自行保證線程安全。

經典爭議話題

  • JVM GC 會回收單例嗎? HotSpot 1.6+ 中,除非人為斷開靜態引用,否則 GC 不會回收單例(因為 GC Roots 可達)。
  • 同一 JVM 能有多個單例嗎? 僅反射、序列化、多類加載器、分布式環境下可能。
  • 懶漢式加 synchronized 線程安全嗎? 安全,但性能損耗大;推薦雙重檢查鎖 + volatile 或靜態內部類寫法。
  • 單例只能繼承嗎? 餓漢/懶漢因 private 建構子不可繼承;登記式單例可繼承。
  • 餓漢 vs 懶漢? Java 推薦餓漢(類載入機制天然線程安全);C++ 常用懶漢。

總結

單例模式簡單但坑深。實務中推薦靜態內部類或枚舉實現,兼顧線程安全、延遲載入、防反射/序列化破壞。切記:單例的核心是「受控唯一」,而非單純的「全局變量」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved