1. 程式人生 > >C#設計模式之創建類模式:單例模式

C#設計模式之創建類模式:單例模式

class style 全局 線程同步 性能 就是 線程安全 應用 過程

在程序的設計過程中很多時候系統會要求對於某個類型在一個應用程序域中只出現一次,或者是因為性能的考慮,或者是由於邏輯的要求,總之是有這樣的需求的存在,那在設計模式中正好有這麽一種模式可以來滿足這樣的要求。

在C#中實現單例模式可以通過定義私有的構造函數來實現,當然,還可以通過定義靜態的構造函數來實現。在Singleton模式中可以利用類的靜態構造器來執行完成單例模式的原因是當靜態變量被訪問的時候CLR會調用類的靜態構造器(類型構造器),創建靜態類的類型對象,CLR希望確保每個應用程序域內只執行一次類型構造器,為了做到這一點,在調用類型構造器時,CLR會為靜態類加一個互斥的線程同步鎖,因此,如果多個線程試圖同時調用某個類型的靜態構造器時,那麽只有一個線程可以獲得對靜態類的訪問權,其他的線程都被阻塞。第一個線程執行完 類型構造器的代碼並釋放構造器之後,其他阻塞的線程被喚醒,然後發現構造器被執行過,因此,這些線程不再執行構造器,只是從構造器簡單的返回。如果再一次調用這些方法,CLR就會意識到類型構造器被執行過,從而不會在被調用。調用類中的靜態方法,或者訪問類中的靜態成員變量,過程同上,所以說靜態成員是線程安全的。

看過上面的描述,可以了解到,靜態成員在C#Runtime中進行了特殊的處理,特別適合建立單例模式。

 public class Singleton
    {
        public static readonly Singleton _instance;

        static Singleton()
        {
            _instance=new Singleton();
        }

        private Singleton()
        {
            
        }
    }

上面簡短的幾行代碼就建立了一個標準的單利模式,其中,定義私有構造函數是為了防止使用new關鍵字在類的外部訪問構造函數,使用靜態的構造函數,是為了初始化這個公共的,共全局訪問的只讀字段_instance。從上面的解釋來看,這種方式還可以免費的使用CLR送的互斥鎖來同步執行並且CLR保證靜態構造函數只被執行一次,也就是說,完美的實現了單例模式的所有要求。因此,這種方法無論從效率還是簡潔上面都是最好的選擇,還有一種雙重判斷的方式來實現單例模式:

 public class AnotherSingleton
    {
        private AnotherSingleton()
        {
            
        }

        private static AnotherSingleton _instance;
        private  static readonly object PadLock=new object();

        public static AnotherSingleton GetInstance()
        {
            if (_instance==null
) { lock (PadLock) { if (_instance==null) { _instance=new AnotherSingleton(); } } } return _instance; } }

利用上面這段代碼也可以建立一個單例模式,但是由於使用鎖,所以初始化方面時間要稍長一些,不過這段代碼實現的單例模式也是適用於在多線程環境下運行的。以上兩個例子就是最常用最好用的單例模式的實現方式。

由於單例模式不用考慮具體的使用環境,只要需求,就可以實現,所以這篇文章就沒涉及到相應的場景。先到這裏吧。

C#設計模式之創建類模式:單例模式