C#設計模式-單例模式

來源:互聯網
上載者:User

標籤:des   style   blog   http   color   io   ar   使用   strong   

前言

最近開始花點心思研究下設計模式,主要還是讓自己寫的代碼可重用性高、保證代碼可靠性。所謂設計模式,我找了下定義:是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編製真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。

為什麼要提倡“Design Pattern(設計模式)”?

根本原因是為了代碼複用,增加可維護性。因此這次我們來學習下設計模式,最後會通過C#語言來實現這些設計模式作為例子,深刻理解其中的精髓。

定義

單例模式,估計是最簡單的一種設計模式了吧。在它的核心結構中只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個執行個體而且該執行個體易於外界訪問,從而方便對執行個體個數的控制並節約系統資源(確保一個類只有一個執行個體,並提供一個全域訪問點)。

特點

  • 1。單例模式的類只提供私人的建構函式
  • 2。類定義中含有一個該類的靜態私人對象
  • 3。該類提供了一個靜態共有的函數用於建立或擷取它本身的靜態私人對象

 

優缺點優點:

一、執行個體控制

單例模式會阻止其他對象執行個體化其自己的單例對象的副本,從而確保所有對象都訪問唯一執行個體。

二、靈活性

因為類控制了執行個體化過程,所以類可以靈活更改執行個體化過程。

缺點:

一、開銷

雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的執行個體,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。

二、可能的開發混淆

使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字執行個體化對象。因為可能無法訪問庫原始碼,因此應用程式開發人員可能會意外發現自己無法直接執行個體化此類。

三、物件存留期

不能解決刪除單個對象的問題。在提供記憶體管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致執行個體被取消分配,因為它包含對該執行個體的私人引用。在某些語言中(如 C++),其他類可以刪除對象執行個體,但這樣會導致單例類中出現懸浮引用。

實現思路

從上面的定義中可以看出,一個單例類要有一個靜態屬性來儲存它唯一的執行個體 ,需要將類的構造方法設定為private,不能在外界通過new建立執行個體,這樣你不允許其他任何類來建立單例類的執行個體,因為它們不能訪問單例類的構造方法。 但是因為其他類不能執行個體化單例類,那麼我們如何使用它呢?答案就是單例類需要提供服務來對外提供類的執行個體,可以定義一個公有方法或者屬性來把該類的執行個體公開出去了。

         一個類能返回對象一個引用(永遠是同一個)和一個獲得該執行個體的方法(必須是靜態方法);當我們調用這個方法時,如果類持有的引用不為空白就返回這個引用,如果類保持的引用為空白就建立該類的執行個體並將執行個體的引用賦予該類保持的引用;同時我們還將該類的建構函式定義為私人方法,這樣其他處的代碼就無法通過調用該類的建構函式來執行個體化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一執行個體

思路明白後,便實現這個Singleton類。

namespace DesignPattern{    /// <summary>    /// 單例模式    /// </summary>    public class Singleton    {        // 定義一個靜態變數來儲存類的執行個體        private static Singleton mySingleton;        // 定義私人建構函式,使外界不能建立該類執行個體        private Singleton()        {        }        //定義公有方法提供一個全域訪問點。        public static Singleton GetInstance()        {            // 如果類的執行個體不存在則建立,否則直接返回            if (mySingleton == null)            {                mySingleton = new Singleton();            }            return mySingleton;        }    }}

這個Singleton單例模式類實現到這裡,我貌似在之前做的asp.net MVC項目中得到了共鳴,原來之前在asp.net的網站中,我用來實現http上下文,工具類等等東西的時候,也用了類似的方法,保證了執行個體化的時候只有一個執行個體,從而減少開銷。

/// <summary>    /// 單例模式    /// </summary>    public class OperateContext    {        #region 擷取當前操作上下文(存線上程中,提高效率) + OperateContext Current        // <summary>        /// 擷取當前操作上下文(存線上程中,提高效率)        /// </summary>        public static OperateContext Current        {            get            {                OperateContext o = CallContext.GetData(typeof(OperateContext).Name) as OperateContext;                if (o == null)                {                    o = new OperateContext();                    CallContext.SetData(typeof(OperateContext).Name, o);                }                return o;            }        }        #endregion        #region Http上下文 以及相關屬性         /// <summary>        /// Http上下文        /// </summary>        HttpContext ContextHttp        {            get            {                return HttpContext.Current;            }        }        HttpResponse Response        {            get            {                return ContextHttp.Response;            }        }        HttpRequest Request        {            get            {                return ContextHttp.Request;            }        }        HttpSessionState Session        {            get            {                return ContextHttp.Session;            }        }        #endregion    }

貼了下之前項目中的一部分代碼,其中裡面還有很多工具類之類訪問比較頻繁的類,於是乎便通過這種方式來提高這個效率,之前做這個項目的時候,這個提高線程效率的方法僅僅是因為需要而學習來的一套做法,原來這個便是設計模式中的一種。

然而這個看似完美的單例其實有那麼一個缺陷,其實這個缺陷在我做網路爬蟲的時候就有遇到過,而且也去解決過,對,你沒有猜錯,便是多線程的問題。也就是如果出現多個線程同時訪問這個方法的時候,就都會建立多個執行個體,這樣就違背了我們單例模式初衷了,這個時候通過Lock自訂的鎖來確保一個時間內只允許一個線程來訪問便可以。

namespace DesignPattern{    /// <summary>    /// 單例模式    /// </summary>    public class Singleton    {        // 定義一個靜態變數來儲存類的執行個體        private static Singleton mySingleton;        // 定義一個標識確保線程同步        private static readonly object locker = new object();        // 定義私人建構函式,使外界不能建立該類執行個體        private Singleton()        {        }        //定義公有方法提供一個全域訪問點。        public static Singleton GetInstance()        {            //這裡的lock其實使用的原理可以用一個詞語來概括“互斥”這個概念也是作業系統的精髓            //其實就是當一個進程進來訪問的時候,其他進程便先掛起狀態            lock (locker)            {                // 如果類的執行個體不存在則建立,否則直接返回                if (mySingleton == null)                {                    mySingleton = new Singleton();                }            }            return mySingleton;        }    }}

        這裡的lock其實使用的原理可以用一個詞語來概括“互斥”這個概念也是作業系統的精髓,其實就是當一個進程進來訪問的時候,其他進程便先掛起狀態。說到互斥,它是指多線程存在時必須互斥訪問的資源。也就是某一時刻不允許多個進程同時訪問,只能單個進程的訪問。我們把這些程式的片段稱作臨界區或臨界段,它存在的目的是有效防止競爭又能保證最大化使用共用資料。而這些並發進程必須有好的解決方案,才能防止出現以下情況:多個進程同時處於臨界區,臨界區外的進程阻塞其他的進程,有些進程在臨界區外無休止的等待。

       上面代碼對於每個線程都會對線程輔助對象locker加鎖之後再判斷執行個體是否存在,對於這個操作完全沒有必要的,因為當第一個線程建立了該類的執行個體之後,此時完全沒必要對線程輔助對象加鎖之後再去判斷,所以上面的實現方式增加了額外的開銷,損失了效能,為了改進上面實現方式的缺陷,我們只需要在lock語句前面加一句(mySingleton==null)的判斷就可以避免鎖所增加的額外開銷,這種實現方式我們就叫它 “雙重鎖定”

namespace DesignPattern{    /// <summary>    /// 單例模式    /// </summary>    public class Singleton    {        // 定義一個靜態變數來儲存類的執行個體        private static Singleton mySingleton;        // 定義一個標識確保線程同步        private static readonly object locker = new object();        // 定義私人建構函式,使外界不能建立該類執行個體        private Singleton()        {        }        //定義公有方法提供一個全域訪問點。        public static Singleton GetInstance()        {            //這裡的lock其實使用的原理可以用一個詞語來概括“互斥”這個概念也是作業系統的精髓            //其實就是當一個進程進來訪問的時候,其他進程便先掛起狀態            if (mySingleton == null)//區別就在這裡            {                lock (locker)                {                    // 如果類的執行個體不存在則建立,否則直接返回                    if (mySingleton == null)                    {                        mySingleton = new Singleton();                    }                }            }            return mySingleton;        }    }}
總結

      到這裡,設計模式的單例模式就一起學習了,xmfdsh我也是第一次接觸這個設計模式,因此會對逐漸對自己寫的設計模式的部落格進行修改和完善,畢竟沒有深入去實踐的時沒有發言權的。從之前做的項目便可以看出,設計模式其實一直就在我們的身邊,只是我們沒有去發現,沒有去總結,而設計模式這種東西也就是前任總結的一套代碼設計經驗的總結,因此學習設計模式比較重要,可以系統的去深入瞭解,

C#設計模式-單例模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.