單實例模式(Singleton)

    單實例模式(Singleton)
    最近一個人好無聊想寫點東西,正好剛學了點設計模式,覺得Singleton這個詞最能引起我的共鳴:( 。Single一個人,ton好多人,‘街道上人潮襯托我的孤單,想象,誰幸運陪在你身旁,卻誤會一場,你也在等你手機響’。暈了, 閒話少說,步入正題。
 
    創建Singleton模式的目的是:‘ensure a class has only one instance, and provide a global point of access to it’. 使用一個全局的靜態變量只能解決global access的問題,當然你也不能期望這個類的用戶會保證only one instance。所以我們需要控制類實例的創建,並且保證任何時候只有一個實例存在。 下面是c++版本的singleton:
// Declaration
class Singleton {
public:
    static Singleton* Instance();
protected:
    Singleton();
private:
    static Singleton* _instance;
}

// Implementation
Singleton* Singleton::_instance = 0;

Singleton* Singleton::Instance() {
    if (_instance == 0) {
        _instance = new Singleton;
    }
    return _instance;
}
 
上面的代碼看起來管用,但在多線程環境下會有潛在的危險。如果有兩個線程同時進入if語句塊,兩個實例會被創建。可以使用臨界區限制同時訪問,但是那樣會對性能帶來不好的影響。
    先看下面的代碼:(c#)
class Singleton
{
    public static Singleton Instance() {
        if (_instance == null) {
            lock (typeof(Singleton)) {
                if (_instance == null) {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;     
    }
    protected Singleton() {}
    private static volatile Singleton _instance = null;
}

上面使用了"double-check"解決了使用臨界區對性能的影響,同時又保證了only one instance.注意使用了volatile關鍵字保證編譯器不做優化.
上面的代碼還是冗長, 既然用.net, 我們可以充分利用.net給我們帶來的方便:
// .NET Singleton 
sealed class Singleton 
{ 
	private Singleton() {} 
	public static readonly Singleton Instance = new Singleton(); 
}
 
大家可能會懷疑這還是Singleton嗎? 先看一個例子:
using System;
/// <summary>
/// Sample Singleton class
/// </summary>
sealed class SingletonCounter
{
    public static readonly SingletonCounter Instance = new SingletonCounter();
    private long Count = 0;
    private SingletonCounter() { }
    public long NextValue()
    {
        return ++Count;
    }
}

class SingletonClient
{
    //[STAThread]
    static void Main()
    {
        for (int i = 0; i < 20; i++)
        {
            Console.WriteLine("Next singleton value: {0}",
                SingletonCounter.Instance.NextValue());
        }
    }
}
 
在vs2005中新建一個c# console項目粘貼上面的代碼,ctrl+F5,一切ok. 下面解釋一下,首先是only one instance, 
.net 在JIT階段, 靜態變量只有在使用時才被實例化, 關於線程安全,.net framework保證了靜態變量初始化安全.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章