单令模式用于保证一个类只有一个实例,C++最常见的写法为
class CSingleton { CSingleton() {} ~CSingleton() {} CSingleton(const CSingleton&); CSingleton& operator= (const CSingleton&); public: static CSingleton& Instance() { static CSingleton obj; return obj; } …… };
通过CSingleton::Instance ()来获得唯一实例的引用。单例模式也许是设计模式模式中最简单的了,但并不然,这里仍有需要解决的问题:
1:多线程环境下,单例对象构造问题
最直接的方法Instance()函数互斥访问,
// 采用双检测来确保多线程安全 template <class T> class YKSingleton { YKSingleton() {} ~YKSingleton() {} YKSingleton(const YKSingleton&); YKSingleton& operator(const YKSingleton&); static T* m_pObj; public: static T& Instance() { if (!m_pObj) { YKScopedLock<YKFastMutex> lock(g_mutex); if (!m_pObj) m_pObj = new T; } return *m_pObj; } }; template <class T> YKSingleton<T>::m_pObj = YK_NULL;
2:因释放顺序,导致引用不存在的单例对象
解决方法:写个类来管理所有的单例对象,将单例对象存入vector中,先创建的单例对象后释放,来解决问题。
class UTIL_API YKSingletonManager { class CHolderSingleton { public: CHolderSingleton() {} virtual ~CHolderSingleton() {} }; template <class T> class CSingleton : public CHolderSingleton { public: CSingleton(T* pObj) : m_pObj(pObj) {} virtual ~CSingleton() { delete m_pObj; } T* m_pObj; }; typedef std::vector<CHolderSingleton*> obj_type; typedef obj_type::iterator obj_iter; typedef obj_type::reverse_iterator obj_rIter; YKSingletonManager(void); ~YKSingletonManager(void); YKSingletonManager(const YKSingletonManager&); YKSingletonManager& operator= (const YKSingletonManager&); static YKSingletonManager& Instance() { static YKSingletonManager obj; return obj; } template <class T> void Insert(T* pObj) { m_singletons.push_back(new CSingleton<T>(pObj)); } template <class T> friend class YKSingleton; private: obj_type m_singletons; };
提供给外界使用的单例框架
template <class T> class YKSingleton { protected: YKSingleton() {} ~YKSingleton() {} YKSingleton(const YKSingleton&); YKSingleton& operator= (const YKSingleton&); static T* m_pSingletonObj; friend class YKSingletonManager::CSingleton<T>; public: static T& Instance() { if (!m_pSingletonObj) { #ifdef YK_THREAD_MULTI YKScopedLock<YKFastMutex> lock(g_mutex); if (!m_pSingletonObj) { #endif // YK_THREAD_MULTI m_pSingletonObj = new T(); YKSingletonManager::Instance().Insert<T>(m_pSingletonObj); #ifdef YK_THREAD_MULTI } #endif // YK_THREAD_MULTI } return *m_pSingletonObj; } }; template <class T> T* YKSingleton<T>::m_pSingletonObj = YK_NULL;
使用方法:
class MyObj : public YKSingleton<MyObj> { }