C 設計模式 單例類

2022-02-02 21:23:27 字數 2144 閱讀 6651

本文假設有乙個manager管理類,**單例類懶漢/餓漢模式的實現,和單例類的多執行緒安全性,最後介紹meyers singleton寫法。

當第一次要用單例類的時候,再產生例項。是一種典型的拖延(lazy)策略。

類宣告:

class manager

;

類定義:

//單例物件指標初始化為nullptr,防止指向了未定義的資料

manager* manager::s_manager = nullptr;

//提供單例類物件訪問

manager* manager::getinstance()

//刪除單例類

void manager::deleteinstance()}

void manager::dosomething()

使用此類時就可以通過:

manager::getinstance()->dosomething();
來運用單例類來做某些操作了。

上面的例子,並不能保證執行緒安全。

假如沒有例項時,某兩個執行緒都幾乎同時使用getinstance(),那麼很可能會產生2份例項,其中乙份還會變成洩露的記憶體。

為了解決執行緒安全問題,本文使用了c++11std::mutex作為互斥鎖,在類額外增加了乙個靜態變數std::mutext s_mtx;

//提供單例類物件訪問

manager* manager::getinstance() //解鎖

return s_manager;

}//刪除單例類

void manager::deleteinstance()

}//解鎖

}

為什麼不是(上鎖,檢查,操作,解鎖)或者(檢查,上鎖,操作,解鎖),而是使用了雙重檢查(檢查,上鎖,檢查,操作,解鎖)?

上鎖的成本遠遠比檢查空指標要高,且當需要產生例項時才需要鎖操作。而實際上大量多次使用getinstance時(因為已經產生了例項)並不需要上鎖,若先上鎖,則會嚴重造成效能阻塞。

僅僅是檢查後再上鎖,則根本沒有做到任何執行緒安全。

餓漢模式與懶漢模式相反,一開始就生成唯一例項。這樣就不用檢查是否存在例項,而且也無需考慮產生例項時的執行緒安全。

class manager ;

//提供單例類物件訪問

manager* manager::getinstance()

使用方法:

manager::getinstance()->dosomething();
可以看到**比懶漢模式簡單多了。在大量使用檢查空指標造成的效能瓶頸而記憶體始終充足時,可以考慮使用餓漢模式

目前最推薦的c++單例寫法

class manager 

private:

manager();

manager(manager const&);

manager& operator = (manager const&);

~manager();

};

這段**很簡單,雖然看上去和懶漢模式類似,只是static變數的位置從類移動到了例項獲取函式內。但是實際上由於c++的機制,當第一次呼叫該函式時,例項才會被構建出來。這樣既可以得到餓漢模式的執行緒安全,又可以有懶漢模式的按需分配的功能。

單例類設計模式算是比較經典的乙個模式,但是需要注意,它並不是想象中那麼美好。

它是一種換皮的全域性變數。

它促進了耦合。

它可能對併發不友好(取決於你使用的單例寫法)。

一些替代方案:

當你僅需要全域性可見的方法時,應該用類靜態方法而不是乙個類例項。

盡可能為例項提供其它便捷的訪問方式(傳參/基類獲取/服務定位器獲取等),而不是通過提供全域性可見的訪問方式。

如果你只是需要類保證只有唯一物件而不需要全域性性,那麼應對外封閉獲取例項介面(其實就是不可全域性獲取例項的)。

所以要注意單例類設計模式不應被泛用,通過上面的替代方案多多少少也就減少了很多不必要的單例設計。

C 設計模式 單例設計模式

對於單例設計模式做乙個簡單的記錄。使用場景 如果乙個類在整個程式的執行環境中,有且僅需乙個例項,可以使用單例設計模式。singleton模式主要設計思路就是用private 或 protected 修飾建構函式,並在全域性維護唯一的例項,通過介面向外部提供這個例項。下面是簡單的 實現。singlet...

C 設計模式 單例設計模式

效果 實現步驟 將建構函式私有化。在類中定義乙個靜態的指標變數 一般設為私有 並在類外初始化為空 定義乙個返回值為類指標的靜態成員函式,如果2中的指標物件為空,則初始化物件,以後再有物件呼叫該靜態成員函式的時候,不再初始化物件,而是直接返回物件,保證類在記憶體中只有乙個例項。解釋 include u...

C 單例設計模式螢幕類練習

題目內容 以單例模式建立乙個螢幕screen物件。輸入格式 用空格分開的兩個整數,代表螢幕解析度 輸出格式 用空格分開的兩個整數,代表螢幕解析度。隨後有換行符 輸入樣例 800 600 輸出樣例 800 600 具體要求 請將如下 中的缺失部分補全 補全screen類中的資料域成員,給出適當的資料型...