近來,我在學習如何在C#語言中使用設計模式中讀到一些資料,其中有關Singleton設計模式引起了我的注意。
學過設計模式的開發人員都知道Singleton模式。我想簡要地解釋一下這個設計模式是為那些尚未學習過設計模式的朋友。Singleton設計模式是告訴您如何在你的應用程式建立一個唯一類樣本的全域對象,也就是說,這個對象只能被執行個體化一次,這個對象同時提供一個訪問它的一個全域的訪問點。這種對象如應用程式中的視窗管理器或者是列印假離線、資料庫連接池等。
現在讓我們先看一下設計模式一書中對Singleton模式的C++實現(為了方便比較,我把實現的代碼寫成內聯的方式):
class Singleton
{
public:
static Singleton* Instance()
{
if(_instance==0)
{
_instance=new Singleton;
}
return _instance;
}
protected:
Singleton();
Private:
Static Singleton* _instance;
};
Stington* Singleton::_instance=0;
這裡我不想對上述的代碼作解釋,大家可以參閱本文後面提供的參考文獻。
為了更好的理解C#,我這裡也出示一下Java中的Singleton模式實現代碼(不是有人認為C#是對Java的剽竊嗎J):
class Singleton
{
public Singleton Instance()
{
if(_instace==null)
{
synchronized (Class.forName("Singleton"))
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
protected Singleton() {}
private static Singleton _instance = null;
}
在上述的Java代碼中使用了雙重檢測機制,來避免多個線程的Singleton執行個體化問題。同樣,我也不想對上述的代碼做任何解釋。
首先,讓我們看一下C#中類似Java的實現:
class Singleton
{
public static Singleton Instance()
{
if(_instance==null)
{
lock (typeof(Singleton))
{
if(_instace==null)
{
_instance=new Singleton();
}
}
}
return _instance;
}
protected Singleton(){}
private static volatile Singleton _instance=null;
}
現在,是我們睜大眼睛的時候了,下面是利用.NET Framework平台優勢實現Singleton模式的代碼:
sealed class Singleton
{
private Singleton();
public static readonly Singleton Instance=new Singleton();
}
非常吃驚是不是,不僅代碼減少了許多,同時也解決了線程問題帶來的效能上損失。有避免了編譯器最佳化的問題。上述的代碼真的能正常工作嗎?如果能,那麼它又是怎樣工作的呢?
注意到,Singleton類被聲明為sealed,以此保證它自己不會被繼承,其次沒有了Instance的方法,將原來_instance成員變數變成public readonly,並在聲明時被初始化。通過這些改變,我們確實得到了Singleton的模式,原因是在JIT的處理過程中,如果類中的static屬性被任何方法使用時,.NET Framework將對這個屬性進行初始化,於是在初始化Instance屬性的同時Singleton類執行個體得以建立和裝載。而私人的建構函式和readonly(唯讀)保證了Singleton不會被再次執行個體化,這正是Singleton設計模式的意圖。
本文不是要討論設計模式,而只是想通過這個例子來說明一件事,那就是精通.NET Framework並將它靈活運用對實際應用開發的重要性。
參考文獻:
——設計模式:可複用物件導向軟體的基礎 [GOF]
——Design Pattern in C# [Jame W Cooper]
——Exploring the Singleton Design Pattern