單態設計模式(Singleton Design Pattern)
1 基本概念
單態模式是設計模式中最為人熟知的也是形式最簡單的。它的基本概念是一個類只生成一個例項。
2 應用
Singleton的應用有很多,譬如對資料庫只能有一個連線,或者對網站的連線數的計數器。
3 幾種形式
基本形式是使用private constructor和一個public的static方法來獲得類的例項。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance() { return instance; } }
Snippet 1
constructor是private,所以如 Singleton s = new Singleton() 不再可行了。只能通過Singleton s = Singleton.getInstance(); 來獲得例項,而這個例項因為是static,全域性共享一個,所以無論有多少個Singleton s = Singleton.getInstance(); 得到的例項都是同一個。
constructor是private,所以如 Singleton s = new Singleton() 不再可行了。只能通過Singleton s = Singleton.getInstance();來獲得例項,而這個例項因為是static,全域性共享一個,所以無論有多少個Singleton s = Singleton.getInstance(); 得到的例項都是同一個。
而Singleton 還有另外一種形式,採用lazy initialization:
public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } }
Snippet 2
Snippet 2同Snippet 1的區別在於:
Snippet 1在load class階段就建立物件了;
而Snippet 2只有第一次要例項化的時候才會建立物件。這就是所謂的lazy initialization。
多執行緒問題
我們來看snippet 2,如果是單執行緒,沒問題,如果是多執行緒,問題就出現了,因為兩個執行緒可以同時進入if(instance == null) 這個判斷語句,所以有可能兩個執行緒建立兩個例項。
public class Singleton { private static Singleton instance = null; private Singleton(){} public static syncronized Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } }
Snippet 3
然而Snippet 3的問題是在建立了物件之後, instance = new Singleton() 這個語句就再也不會執行了,所以對整個方法進行同步的話效率低下,這樣就有人想出了Double-checked locking的方法:
public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance() { if(instance == null) syncronized(Singleton.class){ if(instance == null) instance = new Singleton(); } return instance; } }
Snippet 4
這樣就解決了問題,僅僅對
if(instance == null) instance = new Singleton();
這段程式碼進行同步,如果物件已經被建立,就不會進入到第一個if程式碼段裡面,所以僅僅在第一次建立的時候會進行同步,效率自然高了。現在看來萬無一失了。但問題還沒有這麼簡單。
out-of-order write問題,更多相關資料請見: DoubleCheckedLocking
instance = new Singleton(); 的順序應該是
1 分配記憶體
2 建構函式初始化
3 將物件的reference賦值給instance
但因為Java Memory Model的問題,可能出現下面的所謂out-of-order write的問題:
1 分配記憶體
2 將物件的reference賦值給instance
3 建構函式初始化
也就是還沒對物件初始化,就已經instance != null了,這樣如果另外一個執行緒這時候對例項進行操作,可能有意想不到的結果。
但仍舊沒有好的辦法可以完全解決這個問題。見 參考一 , 參考二
綜上,採用Snippet 1或者Snippet 3比較安全。Snippet 2和Snippet 4最好在多執行緒的環境下不要使用,否則可能會出錯。
4 限制
但Singleton的模式還是有限制的
1 因為採用private constructor,所以Singleton是不能被繼承的。
2 如果應用是在容器中執行,就要小心,因為servlet可能在被幾個classloader載入,同時有幾個Singleton例項存在。
3 另外如果Singleton是可被序列化的(Serializable),如果序列化一次而反序列化多次就有可能有多個Singleton例項存在。關於序列化見此文。
5 結論
所以就算是看起來最簡單的設計模式也有這麼多變數,一不小心就可能落入陷阱。不過當你知道陷阱在哪,也就能避免掉進去了。
相關文件:追MM與Java的23種設計模式
相關文章
- 設計模式--單例(Singleton Pattern)設計模式單例
- 設計模式之單例模式(Singleton Pattern)設計模式單例
- Java設計模式——單例模式(Singleton pattern)Java設計模式單例
- 常用設計模式-單例模式(Singleton pattern)設計模式單例
- PHP設計模式(一)—單例模式(Singleton Pattern)PHP設計模式單例
- Java設計模式之單例模式(Singleton Pattern)Java設計模式單例
- JAVA設計模式之 單例模式【Singleton Pattern】Java設計模式單例
- 設計模式之——Singleton pattern設計模式
- 設計模式之Singleton - 單態模式設計模式
- 單例模式(Singleton Pattern)單例模式
- 建立型模式 --- 單件模式(Singleton Pattern)模式
- [Design Pattern With Go]設計模式-工廠模式Go設計模式
- 什麼是設計模式?(Design Pattern)設計模式
- 我所理解的設計模式(C++實現)——單例模式(Singleton Pattern)設計模式C++單例
- 使用C# (.NET Core) 實現單體設計模式 (Singleton Pattern)C#設計模式
- 設計模式—singleton(單例模式)設計模式單例
- 設計模式 - 單例模式(Singleton)設計模式單例
- 設計模式-狀態模式(State Pattern)設計模式
- Singleton 單例設計模式單例設計模式
- 深入理解 JavaScript 單例模式 (Singleton Pattern)JavaScript單例模式
- 設計模式系列之單例模式(Singleton Pattern)——確保物件的唯一性設計模式單例物件
- java設計模式-單例模式SingletonJava設計模式單例
- 設計模式之單例模式 - Singleton設計模式單例
- 設計模式——3單例模式(Singleton)設計模式單例
- 設計模式之策略模式和狀態模式(strategy pattern & state pattern)設計模式
- 設計模式之狀態模式---State Pattern設計模式
- PHP設計模式(四)單例模式(Singleton)PHP設計模式單例
- 《設計模式》 - 1. 單例模式( Singleton )設計模式單例
- 設計模式--單件模式Singleton(建立型)設計模式
- Java設計模式之單例模式(Singleton)Java設計模式單例
- python: 設計模式(design pattern)之修飾器模式(decorator)Python設計模式
- JAVA設計模式之 狀態模式【State Pattern】Java設計模式
- Scala 與設計模式(一):Singleton 單例模式設計模式單例
- 設計模式(四)Singleton設計模式設計模式
- Singleton設計模式設計模式
- 設計模式的征途—1.單例(Singleton)模式設計模式單例
- 設計模式之“物件效能模式”: Singleton 單例模式(筆記)設計模式物件單例筆記
- 設計模式 - 單例模式Singleton的8種寫法設計模式單例