1. 程式人生 > >C#設計模式學習筆記-單例模式

C#設計模式學習筆記-單例模式

 

 

 

  最近在學設計模式,學到建立型模式的時候,碰到單例模式(或叫單件模式),現在整理一下筆記。

  在《Design Patterns:Elements of Resuable Object-Oriented Software》中的定義是:Ensure a class only has one instance,and provide a global point of access to。它的主要特點不是根據客戶程式呼叫生成一個新的例項,而是控制某個型別的例項數量-唯一一個。(《設計模式-基於C#的工程化實現及擴充套件》,王翔)。也就是說,單例模式就是保證在整個應用程式的生命週期中,在任何時刻,被指定的類只有一個例項,併為客戶程式提供一個獲取該例項的全域性訪問點。

  一、經典模式:

複製程式碼
 
    
     public class Singleton { private static Singleton instance; private Singleton() { } public staticSingleton GetInstance() { if(instance==null) { instance=new Singleton(); } return instance; } }
     
    
     複製程式碼

  解析如下:

  1)首先,該Singleton的建構函式必須是私有的,以保證客戶程式不會通過new()操作產生一個例項,達到實現單例的目的;

  2)因為靜態變數的生命週期跟整個應用程式的生命週期是一樣的,所以可以定義一個私有的靜態全域性變數instance來儲存該類的唯一例項;

  3)必須提供一個全域性函式訪問獲得該例項,並且在該函式提供控制例項數量的功能,即通過if語句判斷instance是否已被例項化,如果沒有則可以同new()建立一個例項;否則,直接向客戶返回一個例項。

  在這種經典模式下,沒有考慮執行緒併發獲取例項問題,即可能出現兩個執行緒同時獲取instance例項,且此時其為null時,就會出現兩個執行緒分別建立了instance,違反了單例規則。因此,需對上面程式碼修改。

  二、多執行緒下的單例模式

  1、Lazy模式

複製程式碼
 
    
     public class Singleton { private static Singleton instance; private static object _lock=newobject(); private Singleton() { } public static Singleton GetInstance() { if(instance==null) {lock(_lock) { if(instance==null) { instance=new Singleton(); } } } return instance; } }
     
    
     複製程式碼
     
    
   

  上述程式碼使用了雙重鎖方式較好地解決了多執行緒下的單例模式實現。先看內層的if語句塊,使用這個語句塊時,先進行加鎖操作,保證只有一個執行緒可以訪問該語句塊,進而保證只建立了一個例項。再看外層的if語句塊,這使得每個執行緒欲獲取例項時不必每次都得加鎖,因為只有例項為空時(即需要建立一個例項),才需加鎖建立,若果已存在一個例項,就直接返回該例項,節省了效能開銷。

  2、餓漢模式

  這種模式的特點是自己主動例項。

複製程式碼
 
    
     public sealed class Singleton { private static readonly Singleton instance=new Singleton();private Singleton() { } public static Singleton GetInstance() { return instance; } }
     
    
     複製程式碼
     
      上面使用的readonly關鍵可以跟static一起使用,用於指定該常量是類別級的,它的初始化交由靜態建構函式實現,並可以在執行時編譯。在這種模式下,無需自己解決執行緒安全性問題,CLR會給我們解決。由此可以看到這個類被載入時,會自動例項化這個類,而不用在第一次呼叫GetInstance()後才例項化出唯一的單例物件。
   
  
   單列模式應該是sealed
   
  

  最近在學設計模式,學到建立型模式的時候,碰到單例模式(或叫單件模式),現在整理一下筆記。

  在《Design Patterns:Elements of Resuable Object-Oriented Software》中的定義是:Ensure a class only has one instance,and provide a global point of access to。它的主要特點不是根據客戶程式呼叫生成一個新的例項,而是控制某個型別的例項數量-唯一一個。(《設計模式-基於C#的工程化實現及擴充套件》,王翔)。也就是說,單例模式就是保證在整個應用程式的生命週期中,在任何時刻,被指定的類只有一個例項,併為客戶程式提供一個獲取該例項的全域性訪問點。

  一、經典模式:

複製程式碼
 
 
  public class Singleton { private static Singleton instance; private Singleton() { } public staticSingleton GetInstance() { if(instance==null) { instance=new Singleton(); } return instance; } }
  
 
  複製程式碼
  
 

  解析如下:

  1)首先,該Singleton的建構函式必須是私有的,以保證客戶程式不會通過new()操作產生一個例項,達到實現單例的目的;

  2)因為靜態變數的生命週期跟整個應用程式的生命週期是一樣的,所以可以定義一個私有的靜態全域性變數instance來儲存該類的唯一例項;

  3)必須提供一個全域性函式訪問獲得該例項,並且在該函式提供控制例項數量的功能,即通過if語句判斷instance是否已被例項化,如果沒有則可以同new()建立一個例項;否則,直接向客戶返回一個例項。

  在這種經典模式下,沒有考慮執行緒併發獲取例項問題,即可能出現兩個執行緒同時獲取instance例項,且此時其為null時,就會出現兩個執行緒分別建立了instance,違反了單例規則。因此,需對上面程式碼修改。

  二、多執行緒下的單例模式

  1、Lazy模式

複製程式碼
 
 
  public class Singleton { private static Singleton instance; private static object _lock=newobject(); private Singleton() { } public static Singleton GetInstance() { if(instance==null) {lock(_lock) { if(instance==null) { instance=new Singleton(); } } } return instance; } }
  
 
  複製程式碼
  
 

  上述程式碼使用了雙重鎖方式較好地解決了多執行緒下的單例模式實現。先看內層的if語句塊,使用這個語句塊時,先進行加鎖操作,保證只有一個執行緒可以訪問該語句塊,進而保證只建立了一個例項。再看外層的if語句塊,這使得每個執行緒欲獲取例項時不必每次都得加鎖,因為只有例項為空時(即需要建立一個例項),才需加鎖建立,若果已存在一個例項,就直接返回該例項,節省了效能開銷。

  2、餓漢模式

  這種模式的特點是自己主動例項。

複製程式碼
 
 
  public sealed class Singleton { private static readonly Singleton instance=new Singleton();private Singleton() { } public static Singleton GetInstance() { return instance; } }
  
 
  複製程式碼
  
   上面使用的readonly關鍵可以跟static一起使用,用於指定該常量是類別級的,它的初始化交由靜態建構函式實現,並可以在執行時編譯。在這種模式下,無需自己解決執行緒安全性問題,CLR會給我們解決。由此可以看到這個類被載入時,會自動例項化這個類,而不用在第一次呼叫GetInstance()後才例項化出唯一的單例物件。