1. 程式人生 > >C# 單例模式的多種簡單實現

C# 單例模式的多種簡單實現

bject summary tor image pan actor 多太 一個 構造函數

什麽是單例模式?

這裏我就不做過多的解釋了, 畢竟關於Singleton的資料實在是太多太多了。點擊這裏

1.簡單的思路就是, 創建對象單例的動作轉移到另外的行為上面, 利用一個行為去創建對象自身, 如下:

   public class Singleton
    {
        private static Singleton _Singleton = null;
        public static Singleton CreateInstance()
        {
            if (_Singleton == null)
            {
Console.WriteLine("被創建"); _Singleton
= new Singleton(); } return _Singleton; } }

這樣寫看上去是沒有問題, 但是有沒有那種可能, 同時兩個動作都判斷這個對象為空, 那麽這個對象就會被創建2次?是的, 多線程中, 這樣是無法保證單例。

技術分享圖片

就像這樣, 同時創建多個線程去創建這個對象實例的時候, 會被多次創建, 這個時候, 對代碼改進一下。

    public class Singleton
    {
        private static Singleton _Singleton = null;
        
private static object Singleton_Lock = new object(); //鎖同步 public static Singleton CreateInstance() { lock (Singleton_Lock) {
            Console.WriteLine("路過");
if (_Singleton == null) {
              Console.WriteLine("被創建"); _Singleton
= new Singleton(); } } return _Singleton; } }

調試代碼:

               TaskFactory taskFactory = new TaskFactory();
                List<Task> taskList = new List<Task>();

                for (int i = 0; i < 5; i++)
                {
                    taskList.Add(taskFactory.StartNew(() =>
                     {
                         Singleton singleton = Singleton.CreateInstance(); 
                     }));
                }

結果:

技術分享圖片

上面, 我們創建了多個線程,同時去創建這個對象的實例, 在第二次,對象命名已經被創建了, 盡管只創建了一次滿足了我們的需求, 但是我們已知對象被創建了, 還需要進來做不必要的動作嗎?

我們都知道, 同步鎖為了達到預期的效果, 也是損耗了性能的, 那麽下面的輸出, 很顯然是沒必要的動作, 所以我們優化一下。

    public class Singleton
    {
        private static Singleton _Singleton = null;
        private static object Singleton_Lock = new object();
        public static Singleton CreateInstance()
        {
            if (_Singleton == null) //雙if +lock
{
lock (Singleton_Lock) { Console.WriteLine("路過。"); if (_Singleton == null) { Console.WriteLine("被創建。"); _Singleton = new Singleton(); } } } return _Singleton; } }

結果:

技術分享圖片

很顯然, 這樣達到了我們的預期, 對象在被創建後, 就沒必要做多余的行為。

利用靜態變量實現單例模式

    public class SingletonThird
    {
        /// <summary>
        /// 靜態變量
/// </summary> private static SingletonThird _SingletonThird = new SingletonThird(); public static SingletonThird CreateInstance() { return _SingletonThird; } }

是不是覺得很優雅, 利用靜態變量去實現單例, 由CLR保證,在程序第一次使用該類之前被調用,而且只調用一次

PS: 但是他的缺點也很明顯, 在程序初始化後, 靜態對象就被CLR構造了, 哪怕你沒用。

利用靜態構造函數實現單例模式

    public class SingletonSecond
    {
        private static SingletonSecond _SingletonSecond = null;

        static SingletonSecond()
        {
_SingletonSecond
= new SingletonSecond(); } public static SingletonSecond CreateInstance() { return _SingletonSecond; } }

靜態構造函數:只能有一個,無參數的,程序無法調用 。

同樣是由CLR保證,在程序第一次使用該類之前被調用,而且只調用一次

同靜態變量一樣, 它會隨著程序運行, 就被實例化, 同靜態變量一個道理。

C# 單例模式的多種簡單實現