定義:確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。 html
類型:建立類模式 java
類圖: 數據庫
類圖知識點: 編程
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++中則通常使用懶漢式單例。
單例模式比較簡單,在此就不舉例代碼演示了。