轉:設計模式Singleton(例子是C#的)
最後更新:2017-02-28
來源:互聯網
上載者:User
設計模式之Singleton
--------------------------------------------------------------------------------
引言
相信大多數拜讀過"Gang Of Four"(Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)的經典之作《Design Pattern》的同僚們,對這本書一定推崇有加。曾有人這麼宣告:"只有在讀過《Design Pattern》後,我的編程水平才真正得到了質的飛躍。"
那麼,如何才能步入設計模式的殿堂?設計模式是資深程式員日積月累總結出來的一套可複用的、針對物件導向軟體設計的解決方案,從這個意義上說,世界上存在無數多的設計模式,"Gang Of Four"總結的23種設計模式只是其中的23個精華。入手的關鍵就在於領會"設計模式"的思想,然後再將它們融會貫通、靈活應用到自己到開發過程中。
--------------------------------------------------------------------------------
Singleton模式
Singleton可以說是《Design Pattern》中最簡單也最實用的一個設計模式。那麼,什麼是Singleton?
顧名思義,Singleton就是確保一個類只有唯一的一個執行個體。Singleton主要用於對象的建立,這意味著,如果某個類採用了Singleton模式,則在這個類被建立後,它將有且僅有一個執行個體可供訪問。很多時候我們都會需要Singleton模式,最常見的比如我們希望整個應用程式中只有一個串連資料庫的Connection執行個體;又比如要求一個應用程式中只存在某個使用者資料結構的唯一執行個體。我們都可以通過應用Singleton模式達到目的。
一眼看去,Singleton似乎有些像全域對象。但是實際上,並不能用全域對象代替Singleton模式,這是因為:其一,大量使用全域對象會使得程式品質降低,而且有些程式設計語言例如C#,根本就不支援全域變數。其二,全域對象的方法並不能阻止人們將一個類執行個體化多次:除了類的全域執行個體外,開發人員仍然可以通過類的建構函式建立類的多個局部執行個體。而Singleton模式則通過從根本上控制類的建立,將"保證只有一個執行個體"這個任務交給了類本身,開發人員不可能再有其它途徑得到類的多個執行個體。這一點是全域對象方法與Singleton模式的根本區別。
--------------------------------------------------------------------------------
Singleton模式的實現
Singleton模式的實現基於兩個要點:
1)不直接用類的建構函式,而另外提供一個Public的靜態方法來構造類的執行個體。通常這個方法取名為Instance。Public保證了它的全域可見度,靜態方法保證了不會建立出多餘的執行個體。
2)將類的建構函式設為Private,即將建構函式"隱藏"起來,任何企圖使用建構函式建立執行個體的方法都將報錯。這樣就阻止了開發人員繞過上面的Instance方法直接建立類的執行個體。
通過以上兩點就可以完全控制類的建立:無論有多少地方需要用到這個類,它們訪問的都是類的唯一產生的那個執行個體。以下C#代碼展現了兩種實現Singleton模式的方式,開發人員可以根據喜好任選其一。
實現方式一:Singleton.cs
using System;
class SingletonDemo
{ private static SingletonDemo theSingleton = null;
private SingletonDemo() {}
public static SingletonDemo Instance()
{ if (null == theSingleton)
{
theSingleton = new SingletonDemo();
}
return theSingleton;
}
static void Main(string[] args)
{ SingletonDemo s1 = SingletonDemo.Instance();
SingletonDemo s2 = SingletonDemo.Instance();
if (s1.Equals(s2))
{ Console.WriteLine("see, only one instance!");
}
}
}
與之等價的另外一種實現方式是:Singleton.cs:
using System;
class SingletonDemo
{ private static SingletonDemo theSingleton = new SingletonDemo();
private SingletonDemo() {}
public static SingletonDemo Instance()
{ return theSingleton;
}
static void Main(string[] args)
{ SingletonDemo s1 = SingletonDemo.Instance();
SingletonDemo s2 = SingletonDemo.Instance();
if (s1.Equals(s2))
{ Console.WriteLine("see, only one instance!");
}
}
}
編譯執行:
Csc Singleton.cs
得到運行結果:
see, only one instance!
--------------------------------------------------------------------------------
.NET中的Singleton
因為Singleton模式具有這樣實用的價值,開發人員除了可以在程式碼中直接使用Singleton模式外,在許多大型系統的實現上也都處處可見它的影子。在微軟隆重推出的.NET架構中,同樣也可以發現Singleton思想閃爍的光芒。
舉例來說,在.NET架構的重要組成部分Remoting中,遠程對象(Remote Object)有兩種啟用方式:伺服器端啟用方式和用戶端啟用方式。採用伺服器端啟用方式的對象又分為兩種類型:Singleton對象和SingleCall對象。Singleton 對象是這樣的對象:無論該對象有多少個用戶端調用,它總是只有一個執行個體,由這個執行個體來處理所有的用戶端請求。相反地,若將遠程對象聲明為 SingleCall,則系統會為每次用戶端方法的調用建立一個新對象,即使這些方法調用來自同一個用戶端,也即,對象只在方法調用持續期間存在,一旦方法調用結束,該對象就會被銷毀。顯而易見,這裡的Singleton對象就是設計模式Singleton思想在.NET中的應用。
那麼,如何在.NET的Remoting中利用Singleton?.NET提供了兩種方式將一個遠程對象註冊為Singleton:直接調用RegisterWellKnownServiceType方法,在參數中指定物件類型為Singleton;或在設定檔web.config中設定遠程對象的類型為Singleton。這兩種方法的效果相同,所不同的是後一種方法顯得更加方便,因為改變更配置置檔案的內容後,不必重新編譯應用程式。下列代碼顯示了如何使用RegisterWellKnownServiceType方法註冊遠程物件類型:
RemotingConfiguration.RegisterWellKnownServiceType( Type.GetType("RemotingSamples.HelloServer,object"), "SayHello", WellKnownObjectMode.Singleton);
參數"SayHello"是用戶端訪問遠程對象(這裡是HelloServer)時用來代表遠程對象的URI,例如tcp://localhost:8085/SayHello(假設使用的是TCP通道)。
最後一個參數就指明了這個遠程對象是Singleton類型。一旦將遠程對象註冊為Singleton,則在第一次用戶端調用HelloServer的方法時建立這個遠程對象,然後保持它直到用戶端中斷串連或對象逾時被銷毀為止。在此期間,無論有多少個用戶端調用這個遠處對象,所有的客戶請求都將由那個已經存在的唯一執行個體接受處理。
這就是Singleton在.NET中的應用。
從Singleton模式的實現和應用中也可以看出,優秀的設計模式往往都具有"簡約之美"。它們採用一種"優雅"的方式,將那些成功的設計方法和體繫結構能夠得以被簡單、方便地複用。這也是為什麼現在的軟體開發日益強調"設計模式"的原因之所在。如果想進一步瞭解更多的設計模式,還是推薦各位閱讀Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides的經典之作《Design Pattern》。
--------------------------------------------------------------------------------
作者:劉英丹