引子
当我们在程序里只需生成类的一个实例时,我们通常会把这个类设计成单件类以保证程序最多只能生成这个类的一个实例。 于是乎如果我们的程序是个比较庞大的系统,而这个程序里头的许多个类都需要设计成单件类时,就会有很多重复的代码。恩,单件类毕竟有很多类似的地方,所以我们可以生成一个单件基类,其它的具体单件类都从这个基类继承。
基本思想
把所有的单件类的实例都存放于单件基类的一个哈希表中,程序中需要用到某个具体单件类的实例时就从这个表中查找。
实现
首先我们定义一些宏:
#define MAX_CLASSNAMELEN 30 // 单件子类名称的最大长度
#define HASHMAPSIZE 10 // 哈希表长度
// 宣告一个单件类宏,classname为子类名称,param为子类构造函数参数列表(可以为空)
#define DECLARE_SINGLETON(classname , param) /
public: /
static classname* GetInstance(); /
static void DestroyInstance(); /
private: /
classname(param);
// 实现单件类的基本函数宏,classname为子类名称,param为子类构造函数参数列表(可以为空)
#define IMPLEMENT_SINGLETON(classname , param) /
classname* classname::GetInstance() /
{ /
classname* pObj = (classname *)(FindInstance(#classname)); /
if( pObj == NULL ) /
{ /
classname* pSingleton = new classname(); /
if( Register(#classname , pSingleton) ) /
return pSingleton; /
} /
else /
{ /
return pObj; /
} /
return NULL; /
} /
/
void classname::DestroyInstance() /
{ /
Unregister(#classname); /
} /
/
classname::classname(#param) : CSingleton(#classname)
// 单件类实例节点
class CSingletonPtr
{
friend class CSingleton;
private :
CSingleton *m_pSingleton;
CSingletonPtr *m_pNext;
public:
CSingletonPtr()
{
m_pSingleton = NULL;
m_pNext = NULL;
};
};
// 单件基类
class CSingleton
{
protected:
CSingleton(const char* szSubClassName);
virtual ~CSingleton();
static bool Register(const char* szSubClassName , CSingleton* pSingleton);
static void Unregister(const char* szSubClassName);
static CSingleton* FindInstance(const char* szClassName);
static int hashMap(const char* szKey);
private:
static CSingletonPtr* m_Singletons[HASHMAPSIZE];
char m_szSubClassName[MAX_CLASSNAMELEN];
};
CSingletonPtr* CSingleton::m_Singletons[HASHMAPSIZE];
bool CSingleton::Register(const char* szSubClassName , CSingleton* pSingleton)
{
if( szSubClassName[0] == '/0' || pSingleton == NULL )
{
return false;
}
int index = hashMap(szSubClassName);
CSingletonPtr* pSingletonPtr = m_Singletons[index];
if( pSingletonPtr == NULL )
{
CSingletonPtr* pTemp = new CSingletonPtr();
pTemp->m_pSingleton = pSingleton;
pTemp->m_pNext = NULL;
m_Singletons[index] = pTemp;
}
else
{
CSingletonPtr* pPreSingletonPtr = pSingletonPtr;
while( 1 )
{
pSingletonPtr = pSingletonPtr->m_pNext;
if( pSingletonPtr == NULL )
{
CSingletonPtr *pTemp = new CSingletonPtr();
pTemp->m_pSingleton = pSingleton;
pTemp->m_pNext = NULL;
pPreSingletonPtr->m_pNext = pTemp;
break;
}
pPreSingletonPtr = pSingletonPtr;
}
}
return true;
}
void CSingleton::Unregister(const char* szSubClassName)
{
if( szSubClassName[0] == '/0' )
{
return;
}
int index = hashMap(szSubClassName);
CSingletonPtr* pSingletonPtr = m_Singletons[index];
if( pSingletonPtr == NULL )
m_Singletons[index] = NULL;
else if( pSingletonPtr->m_pNext == NULL )
{
delete pSingletonPtr;
m_Singletons[index] = NULL;
}
else if( strcmp(szSubClassName , pSingletonPtr->m_pSingleton->m_szSubClassName) == 0 )
{
m_Singletons[index] = pSingletonPtr->m_pNext;
delete pSingletonPtr;
}
else
{
CSingletonPtr *pPre;
pPre = pSingletonPtr;
while( pSingletonPtr )
{
if( strcmp(szSubClassName , pSingletonPtr->m_pSingleton->m_szSubClassName) == 0 )
{
pPre->m_pNext = pSingletonPtr->m_pNext;
delete pSingletonPtr;
break;
}
pPre = pSingletonPtr;
pSingletonPtr = pSingletonPtr->m_pNext;
}
}
}
CSingleton::CSingleton(const char* szSubClassName)
{
strcpy(m_szSubClassName , szSubClassName);
}
CSingleton::~CSingleton()
{
}
CSingleton* CSingleton::FindInstance(const char* szClassName)
{
int index = hashMap(szClassName);
CSingletonPtr* pSingletonPtr = m_Singletons[index];
while( pSingletonPtr )
{
if( strcmp(szClassName , pSingletonPtr->m_pSingleton->m_szSubClassName) == 0 )
return pSingletonPtr->m_pSingleton;
pSingletonPtr = pSingletonPtr->m_pNext;
}
return NULL;
}
int CSingleton::hashMap(const char* szKey)
{
int hashf = 0;
while( *szKey )
hashf += toupper((unsigned char)*szKey++);
return hashf % HASHMAPSIZE;
}
使用
如果我们要生成一个子类,只需如下即可:
class CChild : public CSingleton
{
DECLARE_SINGLETON(CChild , )
public :
void Func();
}
IMPLEMENT_SINGLETON(CChild , )
{
}
void CChild::Func()
{
}