23種設計模式(1):單例模式

定義:確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。 html

類型:建立類模式 java

類圖: 數據庫

23種設計模式(1):單例模式 - 第1張  | 快課網

類圖知識點: 編程

1.類圖分爲三部分,依次是類名、屬性、方法 設計模式

2.以<<開頭和以>>結尾的爲註釋信息 安全

3.修飾符+表明public,-表明private,#表明protected,什麼都沒有表明包可見。 多線程

4.帶下劃線的屬性或方法表明是靜態的。 jvm

5.對類圖中對象的關係不熟悉的朋友能夠參考文章:設計模式中類的關係 分佈式

單例模式應該是23種設計模式中最簡單的一種模式了。它有如下幾個要素: 工具

  • 私有的構造方法
  • 指向本身實例的私有靜態引用
  • 以本身實例爲返回值的靜態的公有的方法

        單例模式根據實例化對象時機的不一樣分爲兩種:一種是餓漢式單例,一種是懶漢式單例。餓漢式單例在單例類被加載時候,就實例化一個對象交給本身的引用;而懶漢式在調用取得實例方法的時候纔會實例化對象。代碼以下:

餓漢式單例

1
2
3
4
5
6
7
public class Singleton {
     private static Singleton singleton = new Singleton ( ) ;
     private Singleton ( ) { }
     public static Singleton getInstance ( ) {
         return singleton ;
     }
}

懶漢式單例

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
     private static Singleton singleton ;
     private Singleton ( ) { }
    
     public static synchronized Singleton getInstance ( ) {
         if ( singleton == null ) {
             singleton = new Singleton ( ) ;
         }
         return singleton ;
     }
}

 

單例模式的優勢:

  • 在內存中只有一個對象,節省內存空間。
  • 避免頻繁的建立銷燬對象,能夠提升性能。
  • 避免對共享資源的多重佔用。
  • 能夠全局訪問。

適用場景:因爲單例模式的以上優勢,因此是編程中用的比較多的一種設計模式。我總結了一下我所知道的適合使用單例模式的場景:

  • 須要頻繁實例化而後銷燬的對象。
  • 建立對象時耗時過多或者耗資源過多,但又常常用到的對象。
  • 有狀態的工具類對象。
  • 頻繁訪問數據庫或文件的對象。
  • 以及其餘我沒用過的全部要求只有一個對象的場景。

單例模式注意事項:

  • 只能使用單例類提供的方法獲得單例對象,不要使用反射,不然將會實例化一個新對象。
  • 不要作斷開單例類對象與類中靜態引用的危險操做。
  • 多線程使用單例使用共享資源時,注意線程安全問題。

關於java中單例模式的一些爭議:

單例模式的對象長時間不用會被jvm垃圾收集器收集嗎

        看到很多資料中說:若是一個單例對象在內存中長久不用,會被jvm認爲是一個垃圾,在執行垃圾收集的時候會被清理掉。對此這個說法,筆者持懷疑態度,筆者本人的觀點是:在hotspot虛擬機1.6版本中,除非人爲地斷開單例中靜態引用到單例對象的聯接,不然jvm垃圾收集器是不會回收單例對象的。

對於這個爭議,筆者單獨寫了一篇文章進行討論,若是您有不一樣的觀點或者有過這方面的經歷請進入文章單例模式討論篇:單例模式與垃圾收集參與討論。

在一個jvm中會出現多個單例嗎

        在分佈式系統、多個類加載器、以及序列化的的狀況下,會產生多個單例,這一點是無庸置疑的。那麼在同一個jvm中,會不會產生單例呢?使用單例提供的getInstance()方法只能獲得同一個單例,除非是使用反射方式,將會獲得新的單例。代碼以下

1
2
3
4
Class c = Class . forName ( Singleton . class . getName ( ) ) ;
Constructor ct = c . getDeclaredConstructor ( ) ;
ct . setAccessible ( true ) ;
Singleton singleton = ( Singleton ) ct . newInstance ( ) ;

這樣,每次運行都會產生新的單例對象。因此運用單例模式時,必定注意不要使用反射產生新的單例對象。

懶漢式單例線程安全嗎

        主要是網上的一些說法,懶漢式的單例模式是線程不安全的,即便是在實例化對象的方法上加synchronized關鍵字,也依然是危險的,可是筆者通過編碼測試,發現加synchronized關鍵字修飾後,雖然對性能有部分影響,可是倒是線程安全的,並不會產生實例化多個對象的狀況。

單例模式只有餓漢式和懶漢式兩種嗎

        餓漢式單例和懶漢式單例只是兩種比較主流和經常使用的單例模式方法,從理論上講,任何能夠實現一個類只有一個實例的設計模式,均可以稱爲單例模式。

 

單例類能夠被繼承嗎

        餓漢式單例和懶漢式單例因爲構造方法是private的,因此他們都是不可繼承的,可是其餘不少單例模式是能夠繼承的,例如登記式單例。

餓漢式單例好仍是懶漢式單例好

        在java中,餓漢式單例要優於懶漢式單例。C++中則通常使用懶漢式單例。

單例模式比較簡單,在此就不舉例代碼演示了。

相關文章
相關標籤/搜索