1. 程式人生 > >設計模式學習筆記(二)單例模式

設計模式學習筆記(二)單例模式

單例模式(Singleton Pattern):

Ensure a class has only one instance, and provide a global point of access to it.

(確保某一個類只有一個例項,並向整個系統提供這個例項的全域性訪問點。)

單例模式的優點:

  • 由於單例模式在記憶體中只有一個例項,減少了記憶體開支,特別是一個物件需要頻繁地建立、銷燬時,單例模式的優勢就非常明顯。
  • 當一個物件的產生需要比較多的資源時,就可以使用單例模式,在程式啟動時直接產生一個單例物件,然後用永久駐留記憶體的方式來解決效能問題。
  • 單例模式可以避免對資源的多重佔用。
  • 單例模式可以在系統設定全域性的訪問點,優化和共享資源訪問。

單例模式的缺點:

  • 單例模式一般沒有介面,擴充套件很困難,只能通過修改程式碼方式實現。
  • 單例模式對測試不利。
  • 單例模式與單一職責原則有衝突。

單例模式的使用場景:

  • 要求生成唯一序列號的環境。
  • 在整個專案中需要一個共享訪問點或共享資料。
  • 建立一個物件需要消耗的資源過多。
  • 需要定義大量的靜態常量和靜態方法(工具類)的環境。

單例模式的注意事項:

首先,在高併發情況下,注意單例模式的執行緒安全問題。

  • 可以用volitail關鍵字修飾單例成員變數,禁止在單例項物件建立過程中的指令重排,用synchronozed關鍵字保證只能有一個執行緒參與例項的建立。
  • 可以用列舉類完成單例建立(每一個列舉物件就是一個單例
  • 可以使用在單例類的內部類定義一個被static final 關鍵字修飾成員變數的的方式建立單例。

其次要考慮物件的複製情況,在Java中,物件預設是不可以被複制的,若實現了Cloneable介面,並實現了clone方法,則可以直接通過物件複製方式建立一個新物件,物件複製是不用呼叫類的建構函式,因此即使是私有的建構函式,物件仍然被複制。最好就是單例類不要實現Cloneable介面。

單例模式的擴充套件:有上限的多例模式。

JVM的垃圾回收機制引起的問題:

如果一個單例物件在記憶體中長久不使用,JVM就認為這個物件是一個垃圾,在CPU資源空閒的情況下該物件會被清理掉,下次再呼叫時就需要重新產生一個物件。

如果確實需要採用單例模式來記錄有狀態的值,有三種方法可以解決該問題:

  • 由容器管理單例的生命週期。
  • 定時重新整理單例物件
  • 狀態隨時進行持久化記錄,重新建立單例項時與持久化記錄內容同步