.NET設計模式(1):1.1 單例模式(Singleton Pattern)

#概述 單例模式就是保證在整個應用程序的生命週期中,在任什麼時候刻,被指定的類只有一個實例,併爲客戶程序提供一個獲取該實例的全局訪問點。數據庫

單例模式是一種經常使用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。經過單例模式能夠保證系統中一個類只有一個實例並且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。若是但願在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。windows


意圖

保證一個類僅有一個實例,並提供一個該實例的全局訪問點。設計模式


場景

  1. Windows的Task Manager(任務管理器)就是很典型的單例模式,任什麼時候候只能打開一個窗口。
  2. windows的Recycle Bin(回收站)也是典型的單例應用。在整個系統運行過程當中,回收站一直維護着僅有的一個實例。
  3. 網站的計數器,通常也是採用單例模式實現,不然難以同步。
  4. 應用程序的日誌應用,通常都何用單例模式實現,這通常是因爲共享的日誌文件一直處於打開狀態,由於只能有一個實例去操做,不然內容很差追加。
  5. Web應用的配置對象的讀取,通常也應用單例模式,這個是因爲配置文件是共享的資源。
  6. 數據庫鏈接池的設計通常也是採用單例模式,由於數據庫鏈接是一種數據庫資源。數據庫軟件系統中使用數據庫鏈接池,主要是節省打開或者關閉數據庫鏈接所引發的效率損耗,這種效率上的損耗仍是很是昂貴的,由於何用單例模式來維護,就能夠大大下降這種損耗。
  7. 多線程的線程池的設計通常也是採用單例模式,這是因爲線程池要方便對池中的線程進行控制。
  8. 操做系統的文件系統,也是大的單例模式實現的具體例子,一個操做系統只能有一個文件系統。
  9. HttpApplication 也是單位例的典型應用。熟悉ASP.Net(IIS)的整個請求生命週期的人應該知道HttpApplication也是單例模式,全部的HttpModule都共享一個HttpApplication實例.

實現

1.將該類的構造方法定義爲私有方法,這樣其餘處的代碼就沒法經過調用該類的構造方法來實例化該類的對象,只有經過該類提供的靜態方法來獲得該類的惟一實例; 2.在該類內提供一個靜態方法,當咱們調用這個方法時,若是類持有的引用不爲空就返回這個引用,若是類保持的引用爲空就建立該類的實例並將實例的引用賦予該類保持的引用。安全

餓漢式

  • 靜態常量(經典寫法)
public class Singleton
{
    private static Singleton _instance = new Singleton();
    private Singleton() { }

    public static Singleton Instance()
    {
        return _instance;
    }
}

適用:單/多線程 模式:餓漢式(靜態常量)[可用] 優勢:寫法比較簡單,避免了線程同步問題 缺點:沒能實現延遲加載多線程

  • 靜態代碼塊
public class Singleton2
{
    private static Singleton2 _instance;

    static Singleton2()
    {
        _instance = new Singleton2();
    }

    private Singleton2(){}

    public Singleton2 Instance()
    {
        return _instance;
    }
}

適用:單/多線程 模式:餓漢式(靜態代碼塊)[可用] 優勢:寫法比較簡單,避免了線程同步問題 缺點:沒能實現延遲加載性能

懶漢式

  • 線程不安全
public class Singleton3
{
    private static Singleton3 _instance;

    private Singleton3() { }

    public static Singleton3 Instance()
    {
        return _instance ?? (_instance = new Singleton3());
    }
}

適用:單線程 模式:懶漢式(線程不安全)[不可用] 優勢:適用於單線程,實現簡單,延遲加載 缺點:多線程不安全,違背了單列模式的原則網站

  • 線程不安全
public class Singleton4
{
    private static Singleton4 _instance;
    private static readonly object SyncObject = new object();

    private Singleton4() { }

    public static Singleton4 Instance()
    {
        lock (SyncObject)
        {
            if (_instance == null)
            {
                _instance = new Singleton4();
            }
        }
        return _instance;
    }
}

適用:單線程 模式:懶漢式(線程安全)[不推薦] 優勢:線程安全;延遲加載; 缺點:這種實現方式增長了額外的開銷,損失了性能(當有多個調用時,第一個調用的會進入lock,而其餘的則等待第一個結束後才能調用,後面的依次訪問、等待……)操作系統

  • 雙重檢查鎖定
public class Singleton5
{
    private static Singleton5 _instance;
    private static readonly object SyncObject = new object();

    private Singleton5() { }

    public static Singleton5 Instance()
    {
        if (_instance==null)
        {
            lock (SyncObject)
            {
                if (_instance == null)
                {
                    _instance = new Singleton5();
                }
            }
        }
        return _instance;
    }
}

適用:單/多線程 模式:雙重檢查鎖定(Double-Check Locking)(線程安全)[推薦] 優勢:線程安全;延遲加載;效率較高(只會實例化一次,首先會判斷是否實例化過,若是實例化了,直接返回實例,不須要進入lock;若是未實例化,進入lock,就算是多個調用也無妨,第一次調用的會實例化,第二個進入lock時會再次判斷是否實例化,這樣線程就不會阻塞了。) 缺點:基本沒有線程

  • 靜態內部類
public class Singleton6
{
    private Singleton6() { }

    private static class SingletonInstance
    {
        public static Singleton6 Instance = new Singleton6();
    }

    public static Singleton6 Instance()
    {
        return SingletonInstance.Instance;
    }
}

適用:單/多線程 模式:靜態內部類(線程安全)[推薦] 優勢:避免了線程不安全;延遲加載;效率高(這種方式跟餓漢式方式採用的機制相似:都是採用了類裝載的機制來保證初始化實例時只有一個線程。不一樣的地方是:餓漢式只要Singleton類被裝載就會實例化,沒有Lazy-Loading的做用;而靜態內部類方式在Singleton類被裝載時並不會當即實例化,而是在須要實例化時,調用Instance方法,纔會裝載SingletonInstance類,從而完成Singleton的實例化。) 缺點:基本沒有設計

相關文章
相關標籤/搜索