說到單例模式,網上搜索出來的結果是多如牛毛,但這不影響我也來湊熱鬧的心情。html
任何事情都是要親身去體會了,才能加深本身的理解。本着不斷學習進取的精神,我很想能夠站在牛人的肩膀上,哪怕是仰視牛人的狀況下,我也想發揮本身的餘熱。記錄下本身學習的足跡,權當本身將來細細回味也好。(不過說真的,本身試着去組織語言來介紹你的問題也好,你的產品也好,能在很大的程度上提升你的表達能力。大腦是越鍛鍊越活的東西,講話、寫做也同樣,鍥而不捨,必有收穫。總之,貴在堅持哦!)數據庫
好了,我先聲明下我參考的牛人文章出處:http://terrylee.cnblogs.com/archive/2005/12/09/293509.htmlwindows
下面來介紹模式,單例模式就是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。設計模式
其實就是實現只有一個門能夠進入,且每次只給一我的進入。這就像之前的一位博友所舉的例子,不少人排隊去廁所蹲坑同樣,每一次只能讓一我的去蹲坑。實現單例模式的緣由,要麼是資源共享,要麼是控制資源等。所謂資源共享,就是由於單例模式保證了一個類僅有一個實例,因此你們訪問的實例是一致的。而控制資源的話,主要是減小資源的申請與釋放等。安全
牛人就是牛人,一下給出了五種實現單例模式的例子。看得我茅塞頓開,大呼過癮。多線程
第一種:簡單實現(惰性實例化) |
namespace Singleton { public class Program { static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } Console.Read(); } } public sealed class Singleton { private Singleton() { } private static Singleton instance = null; public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } } }
簡單實現對於線程來講是不安全的,由於在多線程的狀況下,有可能產生多個Singleton實例。多線程的狀況下,若是多個線程都去判斷(instance == null),而它們都尚未建立實例的狀況下,就會產生多個Singleton實例。對於簡單實現來說,Singleton實例化並非應用程序啓動就建立,因此咱們把它叫作「惰性實例化」,這能避免應用程序啓動時實例化沒必要要的實例。函數
第二種:安全的線程 |
namespace Singleton { public class Program { static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } Console.Read(); } } public sealed class Singleton { private Singleton() { } private static Singleton instance = null; private static readonly object padLock = new object(); public static Singleton Instance { get { lock (padLock) { if (instance == null) { instance = new Singleton(); } return instance; } } } } }
安全的線程,這是對簡單實例的補充。由於提供了加鎖lock()的操做,這就能確保只有一個線程進入。可是加鎖須要增長額外的開銷,損失性能。性能
第三種:雙重鎖定檢查 |
namespace Singleton { public class Program { static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } Console.Read(); } } public sealed class Singleton { public Singleton() { } private static Singleton instance = null;
private static readonly object padLock = new object(); public static Singleton Instance { get { if (instance == null) { lock (padLock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } } }
雙重鎖定檢查在安全的線程上面又進行了改進,主要是考慮了每次加鎖會增長額外的開銷,影響性能。因此在加鎖前再判斷Singleton有沒有被實例化。這樣,它就能減小不少的額外開銷且是線程安全的。實際上,應用程序不多須要上面方式的實現。這種方式仍然有不少缺點:沒法實現延遲初始化。大多數狀況下咱們會使用靜態初始化的方式。學習
第四種:靜態初始化 |
namespace Singleton { public class Program { static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } Console.Read(); } } public sealed class Singleton { static readonly Singleton instance = new Singleton(); private Singleton() { } public static Singleton Instance { get { return instance; } } } }
靜態初始化,是在 .NET 中實現 Singleton 的首選方法。 這段代碼有點意思,我也解讀一下。主要是講解下關鍵字吧。網站
sealed:修改類,意爲這個類不可再被繼承,防止子類被實例化而不能保證只有一個實例的問題。
private Singleton():用private 修改構造函數,能夠防止這個類在外部被實例。也就是在Singleton類外面想new Singleton()是會報編譯錯誤。
static readonly:表示只能在聲明時賦值,或是在靜態構造中賦值。
第五種:延遲初始化 |
namespace Singleton { class Program { static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } Console.Read(); } } public sealed class Singleton { public Singleton() { } public static Singleton Instance { get { return Delay.DelayInstance; } } } public sealed class Delay { private static readonly Singleton delayInstance = new Singleton(); private Delay() { } public static Singleton DelayInstance { get { return delayInstance; } } } }
把實例化的工做交給Delay類開實現,這樣Singleton類就實現了延遲初始化。這種方式具備不少的優點,是值得推薦的一種實現方式。可是這種方式就須要開發人員記住不能使用new關鍵字實例化Singleton。
應用場景 |
其實不論是對於哪一個設計模式來講,咱們總會想知道何時能用到它。畢竟東西不是白學的,是貓是狗總也得帶出來溜溜。
畢竟我也使用得少,因此這裏面爲了讓網友可以看得大而全點,我摘自博友的內容以下:
1. Windows的Task Manager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想一想看,是否是呢,你能打開兩個windows task manager嗎? 不信你本身試試看哦~
2. windows的Recycle Bin(回收站)也是典型的單例應用。在整個系統運行過程當中,回收站一直維護着僅有的一個實例。
3. 網站的計數器,通常也是採用單例模式實現,不然難以同步。
4. 應用程序的日誌應用,通常均可用單例模式實現,這通常是因爲共享的日誌文件一直處於打開狀態,由於只能有一個實例去操做,不然內容很差追加。
5. Web應用的配置對象的讀取,通常也應用單例模式,這個是因爲配置文件是共享的資源。
6. 數據庫鏈接池的設計通常也是採用單例模式,由於數據庫鏈接是一種數據庫資源。數據庫軟件系統中使用數據庫鏈接池,主要是節省打開或者關閉數據庫鏈接所引發的效率損耗,這種效率上的損耗仍是很是昂貴的,由於使用單例模式來維護,就能夠大大下降這種損耗。
7. 多線程的線程池的設計通常也是採用單例模式,這是因爲線程池要方便對池中的線程進行控制。
8. 操做系統的文件系統,也是單例模式實現的具體例子,一個操做系統只能有一個文件系統。
9. HttpApplication 也是單例模式的典型應用。熟悉ASP.Net(IIS)的整個請求生命週期的人應該知道HttpApplication也是單例模式,全部的HttpModule都共享一個HttpApplication實例。
固然若是你有新的使用場景,請不吝賜教:)
至此,本文完!