游戏设计模式——C++单例类
前言:
本文將探討單例類設計模式,單例類的懶漢模式/餓漢模式,單例類的多線程安全性,最后將利用C++模板減少單例類代碼量。
本文假設有一個Manager管理類,并以此為探究單例類的設計模式。
懶漢模式
懶漢模式:顧名思義,是一種典型的拖延(lazy)策略。當第一次要用單例類的時候,再產生實例。
類聲明:
class Manager{ public: ~Manager(); //提供單例對象訪問 static Manager* getInstance(); //刪除單例對象 static void deleteInstance(); void dosomething();protected: //構造函數聲明為 保護方法 Manager(); //單例對象指針 static Manager* s_Manager; }; //單例對象指針初始化為nullptr,防止指向了未定義的數據 Manager* Manager::s_Manager = nullptr;//提供單例類對象訪問 Manager* Manager::getInstance(){ //當沒有存在實例時(一般是指準備第一次用)時,才生成新實例 if(!s_Manager)s_Manager = new CacheManger(); return s_Manager; }//刪除單例類 void Manager::deleteInstance(){ if(s_Manager){deleted s_Manager;s_Manager = nullptr;//別忘了賦予空指針,否則指向未定義數據 } }void Manager::dosomething(){ //dosometing }
這樣我們就能在平時的程序用
Manager::getInstance()->dosomething();來運用單例類來做某些操作了。
?
懶漢模式with線程安全
但是上面的例子,并不能保證線程安全。
假如沒有實例時,然后某兩個線程都幾乎同時使用getInstance(),那么很可能會產生2份實例,其中一份還會變成泄露的內存。
為了解決線程安全問題,自然想到用鎖:(本文使用了C++11 <mutex>的std::mutex作為互斥鎖,在類額外增加了一個靜態變量std::mutext s_mtx;)
//提供單例類對象訪問 Manager* Manager::getInstance() {if (!s_Manager) {//上鎖std::lock_guard<std::mutex> lock(s_mtx);//當沒有存在實例時(一般是指準備第一次用)時,才生成新實例if (!s_Manager){s_Manager = new Manager();}//解鎖 }return s_Manager; }//刪除單例類 void Manager::deleteInstance() {if (s_Manager) {//上鎖std::lock_guard<std::mutex> lock(s_mtx);if (s_Manager) {delete s_Manager;//別忘了賦予空指針,否則指向未定義的數據s_Manager = nullptr;}//解鎖 } }為什么不是(上鎖,檢查,操作,解鎖)或者(檢查,上鎖,操作,解鎖),而是使用了雙重檢查(檢查,上鎖,檢查,操作,解鎖)?
?
餓漢模式
餓漢模式與懶漢模式相反,是程序一開始就生成唯一實例。這樣就不用檢查是否存在實例,而且也無需考慮產生實例時的線程安全。
class Manager { public:~Manager();//提供單例對象訪問static Manager& getInstance();void dosomething(); protected://構造函數聲明為 保護方法 Manager();//單例對象指針static Manager s_Manager; };//提供單例類對象訪問 Manager& Manager::getInstance(){return s_Manager; }使用方法:
Manager::getInstance().dosomething();?可以看到代碼比懶漢模式簡單多了。
在大量使用檢查空指針造成的性能瓶頸而內存始終充足時,可以考慮使用餓漢模式
?
Meyers Singleton(目前最推薦的C++單例寫法)
class Singleton { public:static Singleton& Instance() {static Singleton theSingleton;return theSingleton;} private:Singleton();Singleton(Singleton const&);Singleton& operator=(Singleton const&); ~Singleton(); };這段代碼很簡單,雖然看上去和懶漢模式類似,只是static變量的位置從類移動到了實例獲取函數內。
但是實際上由于C++的機制,當第一次調用該函數時,實例才會被構建出來。
這樣既可以得到餓漢模式的線程安全,又可以有懶漢模式的按需分配的功能。
?
應用場景注意
?單例類設計模式算是比較經典的一個模式,但是需要注意,它并不是想象中那么美好。
一些替代方案:
所以要注意單例類設計模式不應被泛用,通過上面的替代方案多多少少也就減少了很多不必要的單例設計。
?
?
游戲設計模式系列-其他文章:
https://www.cnblogs.com/KillerAery/category/1307176.html
轉載于:https://www.cnblogs.com/KillerAery/p/9097529.html
總結
以上是生活随笔為你收集整理的游戏设计模式——C++单例类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Panda和numpy库和matplot
- 下一篇: 服务器绑定双网卡