設計模式之美:Singleton(單件)


索引

意圖

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

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

結構

參與者

Singleton

  • 定義一個 Instance 操作,允許客戶訪問它的唯一實例。Instance 是一個類操作。
  • 可能負責創建它自己的唯一實例。

適用性

在以下情況下可以使用 Singleton 模式:

  • 當類只能有一個實例並且客戶可以從一個眾所周知的訪問點訪問它時。
  • 當這個唯一實例應該是通過子類化可擴展的,並且客戶應該無需更改代碼就能使用一個擴展的實例時。

缺點

  • 系統檢查開銷。實現中可能每次都需要檢查實例是否存在,這個問題可以通過 Static 實例來解決。
  • 系統資源開銷。通常 Singleton 中的對象一旦被創建,不會被及時銷毀。可以通過提供 Reset 操作來重置。
  • 引起開發混淆。如果類包括 public 構造函數可以在外部構造,當使用 Singleton 對象時,開發人員需要記住不能使用 new 關鍵字來實例化對象。
  • 不易於測試。通常使用 Singleton 時需要考慮是否是反模式,設計是否存在問題。引入 Singleton 或靜態實例會為 Unit Testing 帶來困難。

效果

  • 對唯一實例的受控訪問。
  • 縮小名空間。避免存儲唯一實例的全局變量污染名空間
  • 允許對操作和表示的精化。Singleton 類可以有子類,通過擴展類在運行時刻配置應用。
  • 允許可變數目的實例。控制應用所使用的實例的數目。
  • 比類操作更靈活。比如使用靜態成員函數。

相關模式

  • 很多模式可以使用 Singleton 模式實現。例如:Abstract Factory 可以設計為 Singleton 實例。

實現

實現方式(一):使用 Static 變量初始化 Singleton。

在類加載時即創建實例。缺點是無論使用與否實例均被創建。

 1 namespace SingletonPattern.Implementation1
 2 {
 3   public class Singleton
 4   {
 5     private static Singleton _instance = new Singleton();
 6 
 7     // the constructor should be protected or private
 8     protected Singleton()
 9     {
10     }
11 
12     public static Singleton Instance()
13     {
14       return _instance;
15     }
16   }
17 }

實現方式(二):使用 Lazy Initialization 來實現 Singleton

通常將創建類的唯一實例的操作隱藏在一個類操作后面,由它保證只有一個實例被創建。這個操作可以訪問保存唯一實例的變量,保證在它的首次使用前被創建和初始化。

 1 namespace SingletonPattern.Implementation2
 2 {
 3   public class Singleton
 4   {
 5     private static Singleton _instance;
 6 
 7     // the constructor should be protected or private
 8     protected Singleton()
 9     {
10     }
11 
12     public static Singleton Instance()
13     {
14       if (_instance == null)
15       {
16         // use lazy initialization
17         _instance = new Singleton();
18       }
19 
20       return _instance;
21     }
22   }
23 }

實現方式(三):使用 Reset 來重置 Singleton

可以使用 Reset 操作來將已創建的實例銷毀掉。

 1 namespace SingletonPattern.Implementation3
 2 {
 3   public class Singleton
 4   {
 5     private static Singleton _instance;
 6 
 7     // the constructor should be protected or private
 8     protected Singleton()
 9     {
10     }
11 
12     public static Singleton Instance()
13     {
14       if (_instance == null)
15       {
16         // use lazy initialization
17         _instance = new Singleton();
18       }
19 
20       return _instance;
21     }
22 
23     public void Reset()
24     {
25       _instance = null;
26     }
27   }
28 }

實現方式(四):使用 Double-Check Locking 技術實現 Singleton

Singleton 的實現如果需要保證線程安全性,則可以使用 Double-Check Locking 技術。

 1 namespace SingletonPattern.Implementation4
 2 {
 3   public class Singleton
 4   {
 5     private static Singleton _instance;
 6     private static readonly object _syncRoot = new object();
 7 
 8     // the constructor should be protected or private
 9     protected Singleton()
10     {
11     }
12 
13     public static Singleton Instance()
14     {
15       // double-check locking
16       if (_instance == null)
17       {
18         lock (_syncRoot)
19         {
20           if (_instance == null)
21           {
22             // use lazy initialization
23             _instance = new Singleton();
24           }
25         }
26       }
27 
28       return _instance;
29     }
30   }
31 }

實現方式(五):使用注冊表機制創建和查詢 Singleton 類的子類實例

如果系統中定義了多個 Singleton 的子類,可以實現一個注冊表機制,用於存儲子類的映射。

 1 namespace SingletonPattern.Implementation5
 2 {
 3   public class Singleton
 4   {
 5     private static Dictionary<string, Singleton> _registry
 6       = new Dictionary<string, Singleton>();
 7     private static Singleton _instance;
 8 
 9     // the constructor should be protected or private
10     protected Singleton()
11     {
12     }
13 
14     public static Singleton Instance(string name)
15     {
16       if (!_registry.ContainsKey(name))
17       {
18         if (name == "Apple")
19         {
20           _registry.Add(name, new AppleSingleton());
21         }
22         else if (name == "Orange")
23         {
24           _registry.Add(name, new OrangeSingleton());
25         }
26       }
27 
28       return _registry[name];
29     }
30   }
31 
32   public class AppleSingleton : Singleton
33   {
34   }
35 
36   public class OrangeSingleton : Singleton
37   {
38   }
39 }

設計模式之美》為 Dennis Gao 發布於博客園的系列文章,任何未經作者本人同意的人為或爬蟲轉載均為耍流氓。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM