Singleton模式要求一個類有且僅有一個執行個體,必須自己建立自己的唯一執行個體,必須給所有其它對象提供這一執行個體,並且提供了一個全域的訪問點。這就提出了一個問題:如何繞過常規的建構函式,提供一種機制來保證一個類只有一個執行個體?客戶程式在調用某一個類時,它是不會考慮這個類是否只能有一個執行個體等問題的,所以,這應該是類設計者的責任,而不是類使用者的責任。 從另一個角度來說,Singleton模式其實也是一種職責型模式。因為我們建立了一個對象,這個對象扮演了獨一無二的角色,在這個單獨的對象執行個體中,它集中了它所屬類的所有權力,同時它也肩負了行使這種權力的職責!Singleton模式包含的角色只有一個,就是Singleton。Singleton擁有一個私人建構函式,確保使用者無法通過new直接執行個體它。除此之外,該模式中包含一個靜態私人成員變數instance與靜態公有方法Instance()。Instance方法負責檢驗並執行個體化自己,然後儲存在靜態成員變數中,以確保只有一個執行個體被建立。
Singleton模式是限制而不是改進類的建立;Singleton類中的執行個體構造器可以設定為Protected以允許子類派生;Singleton模式一般不要支援Icloneable介面,因為這可能導致多個對象執行個體,與Singleton模式的初衷違背; Singleton模式一般不要支援序列化,這也有可能導致多個對象執行個體,這也與Singleton模式的初衷違背; Singleton只考慮了對象建立的管理,沒有考慮到銷毀的管理,就支援記憶體回收的平台和對象的開銷來講,我們一般沒必要對其銷毀進行特殊的管理;理解和擴充Singleton模式的核心是“如何控制使用者使用new對一個類的構造器的任意調用”;可以很簡單的修改一個Singleton,使它有少數幾個執行個體,這樣做是允許的而且是有意義的.
using System;
class Singleton
{
private static Singleton instance;
protected Singleton() {}
public static Singleton Instance()
{
if( instance == null )
instance = new Singleton();
return instance;
}
}
public class Client
{
public static void Main()
{
Singleton s1 = Singleton.Instance();
Singleton s2 = Singleton.Instance();
if( s1 == s2 )
Console.WriteLine( "The same instance" );
}
}
幾種簡單實現和優劣比較
1:
public sealed class Singleton
{
static Singleton instance=null;
Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance==null)
{
instance = new Singleton();
}
return instance;
}
}
}
這種方式的實現對於線程來說並不是安全的,因為在多線程的環境下有可能得到Singleton類的多個執行個體。如果同時有兩個線程去判斷(instance == null),並且得到的結果為真,這時兩個線程都會建立類Singleton的執行個體,這樣就違背了Singleton模式的原則。實際上在上述代碼中,有可能在計算出運算式的值之前,對象執行個體已經被建立,但是記憶體模型並不能保證對象執行個體在第二個線程建立之前被發現;由於執行個體是在 Instance 屬性方法內部建立的,因此類可以使用附加功能(例如,對子類進行執行個體化),即使它可能引入不想要的依賴性,直到對象要求產生一個執行個體才執行執行個體化;這種方法稱為“惰性執行個體化”。惰性執行個體化避免了在應用程式啟動時執行個體化不必要的 singleton。
2:
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設計模式的意圖。
(摘自:http://www.cnblogs.com/huqingyu/archive/2004/07/09/22721.aspx )
不過這也帶來了一些問題,比如無法繼承,執行個體在程式一運行就被初始化,無法實現延遲初始化等。
3:
public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
這裡,初始化工作有Nested類的一個靜態成員來完成,這樣就實現了延遲初始化,並具有很多的優勢,是值得推薦的一種實。
4:
public class DataProvider : DataHelper
{
private DataProvider()
{
}
static DataProvider()
{
if (dp == null)
{
dp = new DataProvider();
}
sqlXmlPath = HttpContext.Current.Server.MapPath("SqlXML.xml");
}
private static readonly DataProvider dp = null;
private static readonly string sqlXmlPath;
public static DataProvider Instance
{
get
{
return dp;
}
}
}
Singleton設計模式是一個非常有用的機制,可用於在物件導向的應用程式中提供單個訪問點.