Singleton…
那天看到點部落的高手分享Singleton
忽然想要自己也記錄一下心得
其實我對這個pattern算是特別有印象
為什麼會特別印象深刻呢?
第一:當初小弟在寫actionscript做flash動畫時因為flash的動畫中有時會需要設定某些物件只能在同一場景出現一個
(這些情況使用singleton就很方便,把只能產生一個的責任讓物件本身自己來背算是很適當的處理方式。)
第二:有一次小弟問同事,你覺得哪種pattern最簡單,同事跟我說singleton最簡單,小弟笑了…
關於Singleton這個pattern
其實說簡單也沒那麼簡單
講起來好像很繞舌
其實我想說的是這個pattern要寫很簡單,但是也是有些小地方要注意
小弟分享一下讀書心得~
首先一般來說singleton最基本的兩種寫法
class Singleton
{
    private static Singleton _singleton;
    private Singleton() { }
    public static Singleton GetInstance()
    {
        if (_singleton == null)
        {
            _singleton = new Singleton();
        }
        return _singleton;
    }    
}
class Singleton
{
    private readonly static Singleton _singleton = new Singleton();
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            return _singleton;
        }
    }     
}第一種寫法乍看之下比較不占資源,畢竟成是沒呼叫到Singleton.GetInstance()就永遠不會產生一個singleton物件
但是每一次的呼叫GetInstance就要不斷的判斷if (_singleton == null)也是一個開銷
第二種則是在程式開始執行就產生了一個singleton物件
小弟是覺得如果不一定會instance的話,那也就不需要特地使用它了(將他加到專案中)
當然實務上還是需要在判斷要用哪種做法
另外當使用第一種做法實需要多判斷多執行緒的問題
首先我將第一種做法改成以下
class Singleton
{
    private static Singleton _singleton;
    public static int count = 0;
    private Singleton() { }
    public static Singleton GetInstance()
    {
        Thread.Sleep(1000);
        if (_singleton == null)
        {
            count++;
            _singleton = new Singleton();
        }
        return _singleton;
    }
    public string GetCount()
    {
        return count.ToString();
    }
}每次GetInstance都要等一秒,這樣我比叫好模擬
然後我呼叫的程式如下
Singleton singleton, singleton1;
Action act = new Action(delegate()
{
    singleton = Singleton.GetInstance();
});
Action act1 = new Action(delegate()
 {
     singleton1 = Singleton.GetInstance();
 });
IAsyncResult actResult = act.BeginInvoke(null, null);
IAsyncResult act1Result = act1.BeginInvoke(null, null);
WaitHandle[] waithandlearray = new WaitHandle[] { actResult.AsyncWaitHandle, act1Result.AsyncWaitHandle };
while (!WaitHandle.WaitAll(waithandlearray, 3000, false))
{
}            
Console.WriteLine(Singleton.count.ToString());結果跑到18行時程式給我的count是2。
這就證明了第一種寫法在多執行緒是有可能會出錯的
所以要改成
class Singleton
{
    private static Singleton _singleton;
    private static Object thisLock = new Object();
    private Singleton() { }
    public static Singleton GetInstance()
    {
        if (_singleton == null)
        {
            lock (thisLock)
            {
                _singleton = new Singleton();
            }
        }
        return _singleton;
    }
}
這樣在多執行緒的呼叫中才能確保只會產生一個Singleton物件
如果Singleton不能防止產生超過一個物件的話,那麼這模式也就完全沒任何意義了不是?
這是需要注意的。
有問題請各位大大多多指教,謝謝