設計模式之一(單例模式)

前言

單例模式(Singleton),保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

通常我們可以讓一個全局變量使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是,讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建,並且它可以提供一個訪問該實例的方法。

單例模式

複製代碼
    public class Singleton
    {
        private static Singleton instance;
        private static readonly object SyncRoot = new object();          ///程序運行時創建一個靜態的只讀對象
        private Singleton(){}
        public static Singleton GetInstance()
        {
            ///雙重鎖定   先判斷實例是否存在,不存在再加鎖處理
            ///這樣不用讓線程每次都加鎖,保證了線程安全,也提高了性能
            if (instance == null)   
            {
                lock (SyncRoot)   ///在同一個程序加了鎖的那部分程序只有一個線程可以加入
                {
            ///若實例不存在,則new一個新實例,否則返回已有的實例      
if (instance == null) { instance = new Singleton(); } } } return instance; } }
複製代碼

說明:

構造方法private Singleton(){},讓其private,這樣就堵死了外界利用new創建此類實例的可能

public static Singleton GetInstance() 此方法是獲得本類實例的唯一全局訪問點

lock:是確保當一個線程位於代碼的臨界區時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。

然後在上面的Singleton類中添加一個測試方法

        //類函數
        public void Test()
        {
            Console.WriteLine("Hello World!");
        }

最後即可在控制檯應用程序的入口函數進行調用測試

複製代碼
    class Program
    {
        static void Main(string[] args)
        {
            Singleton.GetInstance().Test();
            Console.ReadLine();
        }
    }
複製代碼

結果也Ok

            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();
            if (s1 == s2)
            {
                Console.WriteLine("兩個對象是相同的實例");
            }

繼續在Main函數中添加實例代碼,判斷兩個實例化對象是否爲一個對象。

 

靜態初始化

 其實咋實際應用當中,C#與公共語言運行庫也提供了一種“靜態初始化”方法,這種方法不需要開發人員顯示的編寫線程安全代碼,即可解決多線程環境下它是不安全的問題。

複製代碼
    public sealed class Singletons
    {
        private static readonly Singletons instance = new Singletons();   
        private Singletons() { }
        public static Singletons GetInstance()
        {
            return instance;
        }
    }
複製代碼

通過sealed修飾符來修飾類,是阻止發生派生,而派生可能會增加實例

在第一次引用類的任何成員時創建實例。公共語言運行庫負責處理變量初始化。並通過readonly標記instance變量,這意味着只能在靜態初始化期間或在類構造函數中分配變量。由於這種靜態初始化的方式是在自己被加載時就將自己實例化,所以被形象的稱之爲餓漢式單例類,上面的單例模式處理方式是要在第一次被引用時,纔會將自己實例化,所以就被成爲懶漢式單例類。

總結

 餓漢式,即靜態初始化的方式,它是類一加載就實例化對象,所以要提前佔用系統資源。然後懶漢式,又會面臨着多線程訪問的安全性問題,需要做雙重鎖定這樣的處理纔可以保證安全。送一到底使用哪一種方式,取決於實際的需求。從C#語言的角度來講,餓漢式的單例類已經足夠滿足我們的需求了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章