今天我們來探索一下Singleton設計模式的實現及應用場景。 Singleton模式屬於Creational Type(創建型)設計模式的一種。該模式一般用於確保在應用中僅創建一個某類的instance,在應用中的各個地方對該類的實例對象的引用均指向同一instacne。 Singleton模式的 ...
今天我們來探索一下Singleton設計模式的實現及應用場景。
Singleton模式屬於Creational Type(創建型)設計模式的一種。該模式一般用於確保在應用中僅創建一個某類的instance,在應用中的各個地方對該類的實例對象的引用均指向同一instacne。
Singleton模式的優勢:它提供了對資源的concurrent(一致)訪問,避免了創建多個實例對象,浪費記憶體空間。
Singleton模式實現準則:
1、確保僅有一個類的實例對象
2、提供對唯一實例對象的全局訪問,該規則又可細分為3條規則。
- 聲明該類的所有構造器為private
- 提供返回實例對象的引用的靜態方法
- 實例對象被存儲為類的private static欄位
下麵通過例子實現Singleton模式,在具體實現時,我們首先實現不使用Singleton模式的代碼,然後一步一步地將其改造成Singleton模式。
1 namespace Singleton 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Singleton s1 = new Singleton(); 8 s1.PrintMessage("this is first message"); 9 10 Singleton s2 = new Singleton(); 11 s2.PrintMessage("this is second message"); 12 13 Console.ReadKey(); 14 } 15 } 16 class Singleton 17 { 18 private static int counter = 0; 19 public Singleton() 20 { 21 counter++; 22 Console.WriteLine("這是第"+counter.ToString()+"次調用構造函數"); 23 } 24 public void PrintMessage(String str) 25 { 26 Console.WriteLine(str); 27 } 28 } 29 }
運行結果如下圖:
可以看出,在不使用Singleton模式時,每次使用類Singleton的PrintMessage方法時,都需要創建一個新的實例對象,這造成了極大的浪費。下麵我們按照上面所說的準則將它改造成使用Singleton模式。
1 namespace Singleton 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Singleton s1 = Singleton.getInstance; 8 s1.PrintMessage("this is first message"); 9 10 Singleton s2 = Singleton.getInstance; 11 s2.PrintMessage("this is second message"); 12 13 Console.ReadKey(); 14 } 15 } 16 public sealed class Singleton 17 { 18 private static int counter = 0; 19 private static Singleton instance=null; 20 21 public static Singleton getInstance 22 { 23 get 24 { 25 if (instance == null) 26 instance = new Singleton(); 27 return instance; 28 } 29 } 30 private Singleton() 31 { 32 counter++; 33 Console.WriteLine("這是第"+counter.ToString()+"次調用構造函數"); 34 } 35 public void PrintMessage(String str) 36 { 37 Console.WriteLine(str); 38 } 39 } 40 }
運行結果如下圖:
另外,需要註意的是,不要忘了在Singleton類的聲明中添加sealed關鍵字,它確保了Singleton類不可被繼承。當Singleton類可被繼承且繼承類位於Singleton基類外部時,由於Singleton基類的構造函數聲明為private,此時運行程式會產生Singleton.Singleton()受保護級別限制不可訪問的編譯錯誤;當Singleton類可被繼承且繼承類位於Singleton基類內部構成嵌套類時,這時在main()方法中就可以創建多個繼承類的instance,這就違背了Singleton模式的設計初衷:僅能創建該類型的一個instance。
最後,上述代碼僅在單線程環境中運行良好,在下篇中介紹多線程環境中的實現,及Double-checked locking和lazy initialization的相關概念。