最近在写一个播放器软件,里面的配置类,我考虑了一下准备用单例模型而且是线程安全的。
不过考虑到代码的重用性,准备把单例模型的实现部分抽象出来,用一个模板函数来实现
实现代码如下:
template<typename SingletonType>
SingletonType* GetSingleton(SingletonType** oneInstance,
CSimpleCriticalSection & clsCriticalSection)
{
//判断某个指针是否为NULL的操作最好抽象成一个模板函数
if (UTIL_COMMONFUN::IsNull(*oneInstance))
{
//EnterCriticalSection(g_clsCriticalSection);
clsCriticalSection.Lock();
if (UTIL_COMMONFUN::IsNull(*oneInstance))
{
*oneInstance = new SingletonType ();
}
clsCriticalSection.UnLock();
// LeaveCriticalSection(g_clsCriticalSection);
}
return *oneInstance;
}
注意:CSimpleCriticalSection类是用来封装临界区的,当然也可以使用MFC中的CCriticalSection,由于工程的特殊性,此处并没有使用。
但是现在遇到了一个问题,那就是单例模型中往往需要另类的一个静态对象,单例类框架如下:
class Singleton
{
private:
static Singleton* g_Singleton;
static CSimpleCriticalSection g_simpleCS;
Singleton(void);
public:
//这个函数也可以进行抽象,因为其他类也有可能需要单例模式
static Singleton* GetInstace()
{
return GetSingleton(&g_Singleton,g_simpleCS);
}
virtual ~CAppSettings(void);
}
也就是说这个静态对象是私有的,如果是公有的也就没有什么意义了。
但是这个地方就出现问题了,由于是私有的,我们的模板函数就没有权限访问这个实例了,编译的时候会出现错误。
在C++中有一个比较特殊的函数,那就是友元函数,他可以毫无禁忌的访问类的任何变量!
我们很容易想到在这个地方声明GetSingleton为类的友元函数,更正后的类如下:
class Singleton
{
private:
static Singleton* g_Singleton;
static CSimpleCriticalSection g_simpleCS;
Singleton(void);
template<typename SingletonType>
friend SingletonType* GetSingleton(SingletonType** oneInstance,
CSimpleCriticalSection & clsCriticalSection);
public:
//这个函数也可以进行抽象,因为其他类也有可能需要单例模式
static Singleton* GetInstace()
{
return GetSingleton(&g_Singleton,g_simpleCS);
}
virtual ~CAppSettings(void);
}
但是这样比较麻烦,每次实现单例模型时候,都需要写这样一大段的声明,劳神费时的。
怎么办?宏定义!
考虑到用宏定义是跟着微软的MFC学的,学过MFC的人应该都知道MFC的消息映射是怎么实现的吧,这里就不多介绍了。
看我的宏定义:
//预实现单例模型的类,都必须进行声明
#ifndef DECLARE_SINGLETON_CLASS
#define DECLARE_SINGLETON_CLASS(theClass) /
template<typename SingletonType> /
friend SingletonType* GetSingleton(SingletonType** oneInstance,/
CSimpleCriticalSection & clsCriticalSection);
#endif