我會寫關於c++11的一個系列的文章,會講到如何使用c++11改進我們的程序,本次講如何改進我們的模式,會講到如何改進單例模式、觀察者模式、訪問者模式、工廠模式、命令模式等模式。通過c++11的改進,我們的模式變得更通用、更簡潔、更強大。本次講如何改進單例模式。
在c++11之前,我們寫單例模式的時候會遇到一個問題,就是多種類型的單例可能需要創建多個類型的單例,主要是因為創建單例對象的構造函數無法統一,各個類型的形參不盡相同,導致我們不容易做一個所有類型都通用的單例。現在c+11幫助我們解決了這個問題,解決這個問題靠的是c++11的可變模板參數。直接看代碼。
template <typename T> class Singleton { public:
template<typename... Args>
static T* Instance(Args&&... args)
{
if(m_pInstance==nullptr)
m_pInstance = new T(std::forward<Args>(args)...);
return m_pInstance;
}
static T* GetInstance()
{
if (m_pInstance == nullptr)
throw std::logic_error("the instance is not init, please initialize the instance first");
return m_pInstance;
}
static void DestroyInstance() { delete m_pInstance; m_pInstance = nullptr; } private: Singleton(void); virtual ~Singleton(void); Singleton(const Singleton&); Singleton& operator = (const Singleton&); private: static T* m_pInstance; }; template <class T> T* Singleton<T>::m_pInstance = nullptr;
這個單例模式可以解決不同類型構造函數形參不盡相同的問題,真正意義上對所有類型都通用的單例模式。
/***********更新說明****************/
由於原來的接口中,單例對象的初始化和取值都是一個接口,可能會遭到誤用,更新之后,講初始化和取值分為兩個接口,單例的用法為:先初始化,后面取值,如果中途銷毀單例的話,需要重新取值。如果沒有初始化就取值則會拋出一個異常。
增加Multiton的實現
#include <map> #include <string> #include <memory> using namespace std; template < typename T, typename K = string> class Multiton { public: template<typename... Args> static std::shared_ptr<T> Instance(const K& key, Args&&... args) { return GetInstance(key, std::forward<Args>(args)...); } template<typename... Args> static std::shared_ptr<T> Instance(K&& key, Args&&... args) { return GetInstance(key, std::forward<Args>(args)...); } private: template<typename Key, typename... Args> static std::shared_ptr<T> GetInstance(Key&& key, Args&&...args) { std::shared_ptr<T> instance = nullptr; auto it = m_map.find(key); if (it == m_map.end()) { instance = std::make_shared<T>(std::forward<Args>(args)...); m_map.emplace(key, instance); } else { instance = it->second; } return instance; } private: Multiton(void); virtual ~Multiton(void); Multiton(const Multiton&); Multiton& operator = (const Multiton&); private: static map<K, std::shared_ptr<T>> m_map; }; template <typename T, typename K> map<K, std::shared_ptr<T>> Multiton<T, K>::m_map;
c++11 boost技術交流群:296561497,歡迎大家來交流技術。