单令模式用于保证一个类只有一个实例,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>
{
}