閱讀986 返回首頁    go 阿裏雲 go 技術社區[雲棲]


設計模式之單例模式

       單例模式:

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

        結構圖:

                     

       經典模式:

 static void Main(string[] args)
        {
            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();
            if (s1==s2)//比較兩次實例化後對象的結果是實例相同
            {
                Console.WriteLine("兩個對象是相同的實例。");
            }
            Console.Read();
        }
        class Singleton
        {
            private static Singleton instance;
            private Singleton ()//構造方法讓其private,這就堵死了外界利用new創建此類實例的可能
            {
            }
            public static Singleton GetInstance()//此方法是獲得本類實例的唯一全局訪問點
            {
                if (instance ==null)//若實例不存在,則new一個新實例,否則返回已有的實例
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }

        多線程的單例:

                      應用場景:多線程的程序中,多個線程同時訪問Singleton類,調用GetInstance()方法,會有可能造成創建多個實例

                 處理:給進程加一把鎖,lock是確保黨一個線程位於代碼段的臨界區時,另一個線程不進入臨界區,如果其他線程試圖進入鎖定的代碼,則它將一直等待,知道該對象被釋放。

               代碼實現:

 static void Main(string[] args)
        {
            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();
            if (s1==s2)
            {
                Console.WriteLine("兩個對象是相同的實例。");
            }
            Console.Read();
        }
        class Singleton
        {
            private static Singleton instance;
            private static readonly object syncRoot=new object();//程序運行時創建一個靜態隻讀的進程輔助對象
            private Singleton ()//構造方法讓其private,這就堵死了外界利用new創建此類實例的可能
            {
            }
            public static Singleton GetInstance()//此方法是獲得本類實例的唯一全局訪問點
            {
                lock(syncRoot)//在同一個時刻加了鎖的那部分程序隻有一個線程可以進入
                {
                    if (instance ==null)//若實例不存在,則new一個新實例,否則返回已有的實例
                    {
                        instance = new Singleton();
                    }
                    return instance;
            }
        }

        靜態初始化:

                    這種方法不需要開發人員顯式地編寫線程安全代碼,即可解決多線程環境下它是不安全的問題。            

static void Main(string[] args)
        {
            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();
            if (s1==s2)
            {
                Console.WriteLine("兩個對象是相同的實例。");
            }
            Console.Read();
        }
        class sealed class Singleton//阻止發生派生,而派生可能會增加實例
        {
            private static readonly Singleton instance=new Singleton ();//在第一次引用類的任何成員時,創建實例。公共語言運行庫負責處理變量初始化
            private Singleton(){}
            public static  Singleton GetInstance()
            {
                return instance;
            }
        }
          關於單例的問題不止我寫的這些,還很多,多線程的單例、雙重鎖定、靜態初始化,這幾種方法在應用時需要靈活掌握,如果用合適了,效果一定非常好,所以在進行單例模式的應用時要多想,多用。







最後更新:2017-04-03 12:55:08

  上一篇:go android之listview緩存圖片(緩存優化)
  下一篇:go openstack 命令行管理八 - 服務管理 (備忘)