設計模式的C++實現 1.單例模式__C++

來源:互聯網
上載者:User

單例模式即實現單例類,即系統中一個類只有一個執行個體,而且該執行個體易於外界訪問。這樣方便對執行個體個數進行控制並節約系統資源。

而單例常用與一些非局部靜態對象,對於這些對象,程式難以控制,對於這些存在與全域,且一般持久存在的對象,有時需要按照一定約束或順序來進行初始化,而初始化這些對象如果不使用單例方法的話會極度不安全。這個時候就要使用單例模式來解決這個問題。

實現單例的方法有很多,最簡單的一個是將對象放入函數中作為其靜態成員:

class SingleTon;SingleTon* getSingleTonInstance(){static SingleTon* instance = new SingleTon(); return instance;}class SingleTon{friend SingleTon* getSingleTonInstance();private:SingleTon(){}};
這是我認為的最簡單的實現單例模式的方法,不足的地方在於這個獲得單例對象的函數不在類內。首先要實現單例模式,將建構函式聲明為稀有,這樣建構函式就不能被方法,也不能隨意建立單例類的對象。而這裡獲得執行個體為函數的靜態對象,所以其只有一個,且存在時間為建立到程式結束。

當然,也可以將函數中的靜態對象改為類中的靜態對象,而將這個全域的函數設定為類中的靜態函數,這樣就得到一個更加普遍常用的形式:

class SingleTon{public:static SingleTon* getInstance(){static SingleTon* instance = new SingleTon();return instance;}~SingleTon(){}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);};
這裡還是使用了函數中的靜態成員,使用類中的靜態成員也是可以的:

class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance)instance = new SingleTon();return instance;}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;};SingleTon* SingleTon::instance;// = new SingleTon();類內的靜態成員初始化可以調用類中的私人的建構函式。

為了安全性,這裡將複製建構函式和賦值操作符都給隱藏了,但是解構函式還是可見的,程式員還是會誤用delete來刪除這個單例實體,這樣是不安全的,可以選擇將解構函式放入私人中,隱藏解構函式,對於一些對象在最後結束時析構,則不用關心其釋放過程。

但是如果在程式執行中要調用解構函式進行執行個體的刪除的話,就使用一個公有的函數來封裝解構函式,且將解構函式置為私人:

class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance)instance = new SingleTon();return instance;}static void delelteInstance(){if(NULL != instance){delete instance;instance = NULL;}}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon();};SingleTon* SingleTon::instance ;

這裡就已經基本上在單線程上安全了,然後就考慮多線程,當多個線程企圖同時初始化 單例執行個體時,就出現了問題,要使用互斥來解決問題,這裡就使用臨界區來解決:

CRITICAL_SECTION cs;class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance){EnterCriticalSection(&cs); if(NULL == instance){//雙檢鎖,在進入臨界區後再檢測一次是否對象已經建立instance = new SingleTon();}LeaveCriticalSection(&cs);  }return instance;}static void delelteInstance(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs);  }}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon();};SingleTon* SingleTon::instance ;
這裡使用雙檢鎖的機制,第一次是判斷是否需要對執行個體進行操作,第二次是在進入臨界區即對資料加鎖後,判斷在資料已經不會再被外界幹擾的情況下,第一次判斷和第二次判斷之間是否被其他線程進行了操作,這樣兩次判斷保證了執行個體的安全。

但是這樣還是不夠安全,因為多線程中還是會有一些特殊情況,在類中一些檔案被鎖了,如檔案控制代碼,資料庫連接等,這些隨著程式的關閉並不會立即關閉資源,必須要在程式關閉前,進行手動釋放。這裡的指不會自動關閉,是對於解構函式是私人的情況下,由於系統無法訪問私人的解構函式,對於沒有這些串連時,即類只在記憶體中佔據了一些地址,則系統將其視為全域變數,在結束時釋放其所在記憶體資源,所以沒有記憶體流失。而若類中有檔案控制代碼和資料庫連接這些東西,系統並不會幫忙關閉這些,所以必須手動的調用解構函式中對這些檔案的關閉操作。

對於這樣的情況,一般會使用一種私人內嵌類Garbo,意為垃圾工人,在單例類中包含一個私人的靜態垃圾工人對象,當程式結束時,系統會調用這個對象的解構函式,而這個解構函式中對單例類對象實現析構。

CRITICAL_SECTION cs;class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance){EnterCriticalSection(&cs); if(NULL == instance){//雙檢鎖,在進入臨界區後再檢測一次是否對象已經建立instance = new SingleTon();}LeaveCriticalSection(&cs);  }return instance;}static void delelteInstance(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs);  }}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon(){}//相應的關閉串連等操作class GarBo{public:~GarBo(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs);  }}};static GarBo gc ;};SingleTon* SingleTon::instance ;SingleTon::GarBo  SingleTon::gc;//類外的初始化。
這樣就獲得一個比較完美的單例類了。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.