最近因為專案告一段落,在網路上看看有什麼新文章時,發現了一些新的作法,原文是英文,在此只是簡單做個記錄,與用自己的方式記錄幾個方法,有興趣看詳情的請參考原文....

參考文章:Implementing the Singleton Pattern in C#

Singleton  顧名思義就是在一個專案中,只能允許一個實體,不管被建立幾次,都是同一個實體。

 

 

一般來說,最簡單的作法:

    public class Singleton
    {
        private static Singleton _instance;

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Singleton();
                return _instance;
            }
        }
    }

上述的作法是個最簡單的方式,但是在現在多執行序的環境上,其實是很容易產生衝突,因此有了以下的新作法:

public class Singleton
    {
        private static readonly object Mutex = new object();
        private static volatile Singleton _instance;

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (Mutex)
                    {
                        if (_instance == null)
                            _instance = new Singleton();
                    }
                }
                return _instance;
            }
        }
    }

利用了一個 Mutex 的物件,透過 lock 的方式,讓第一個執行序可以安全的建立實體,後續的執行序可以等候實體建立完成,可以避免互相打架的方式,在 C# 的環境中,其實可以簡化為下面的方式:

public class Singleton
    {
        private static readonly Singleton _instance = new Singleton();

        private Singleton() { }

        public static Singleton Instance { get { return _instance; } }
    }

此作法可說是 Singleton 最簡單最簡短的方式了,又可避免掉多執行序的問題,因此前面第一個方式,是很不建議使用的。

在某些時刻,我們希望可以做到延遲載入實體,等到要真正使用的時候,在將實體建立出來。在 .NET 4.0 之前的作法如下:

public class Singleton
    {
        private static class SingletonHolder
        {
            internal static readonly Singleton Instance = new Singleton();

            static SingletonHolder() { }
        }

        private Singleton() { }

        public static Singleton Instance { get { return SingletonHolder.Instance; } }

        public static void SayHi()
        {
            Console.WriteLine("Hi All ~~");
        }

        public void DoSometing()
        {
            Console.WriteLine("Do Someting ....");
        }
    }

透過一個子類別 SingletonHolder 來達到延遲載入的作法,在 .NET 4.0 之後,因為新增了一個 Lazy<T> 的泛型類別,因此可在簡化成如下:

public class Singleton
    {
        private static readonly Lazy<Singleton> LazyInstance = new Lazy<Singleton >(() => new Singleton());

        private Singleton() { }

        public static Singleton Instance { get { return LazyInstance.Value; } }

        public static void SayHi()
        {
            Console.WriteLine("Hi All ~~");
        }

        public void DoSometing()
        {
            Console.WriteLine("Do Someting ....");
        }
    }

以上的方式為簡單記錄每總 Singleton 的做法,在新的 .NET 4.0 環境,建議如果可以請使用最後的這一個方法。

 

以上僅供參考~


文章標籤
創作者介紹
創作者 王圓外 的頭像
王圓外

威力手記本

王圓外 發表在 痞客邦 留言(2) 人氣()


留言列表 (2)

發表留言
  • srxrrr
  • 謝謝詳細且易懂的整理!!
    非常實用!!
  • Lu Alumi
  • 首先感謝版大講解的超級詳細, 小弟非常欣賞你的文筆包含code!!!

    但有點小bug...

    Lazy<T> 因為是泛型類別

    宣告Lazy物件時需要給他泛型類別

    所以最後一段程式碼應該成:

    private static readonly Lazy<Singleton> LazyInstance = new Lazy<Singleton> ();
  • 謝謝你的告知,立馬修正。

    王圓外 於 2016/04/20 11:04 回覆

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼