Singleton模式与在Ogre中的实现
Singleton模式的用意是对于一个Class全局只能创建一个实例。常规的做法是把构造函数藏起来,然后通过静态方法返回唯一的一个静态实例。
class Singleton
{
private:
static Singleton *ms_Instance;
public:
Static Singleton* GetInstance()
{
If (!ms_instance)
{
ms_instance = new Singleton();
}
}
protected:
Singleton()
{
}
}
如果我们想让Singleton的子类也具有唯一性,只需要在GetInstance中根据参数指定实例化哪一个子类,就像GOF中所写的,不过这样也只能实例化Singleton的N多子类中的一个,另一个可替代的方法是查表。但是这样的话,以后每增加一个子类都需要修改表。
Ogre中提供了一种方法可以解决这个问题。使用模版类和具化模版:
template <typename T>
class Singleton
{
protected:
static T* ms_Singleton;
public:
Singleton( void )
{
assert( !ms_Singleton );
ms_Singleton = static_cast< T* >( this );
}
~Singleton( void )
{
assert( ms_Singleton );
ms_Singleton = 0;
}
static T& getSingleton( void )
{
assert( ms_Singleton );
return ( *ms_Singleton );
}
static T* getSingletonPtr( void )
{
return ms_Singleton;
}
};
继承于它的类:
class MyClass :public Singleton<MyClass>
做了两件事,1.继承;2.模版具化。对于Singleton中的ms_Singleton也声明了它的类型,只不过还要重新定义:
Template<> MyClass* Singleton<MyClass>:: ms_Singleton = 0;
当你在试图两次实例化MyClass,就会引起assert中断,Ogre这样做是有目的的,因为它所有Manager都是在Root中new出来的。限制了不能在其它地方new,有利于结构的合理性。
另外OGRE中对每个继承于Singleton的子类都抄写了一遍getSingleton(void)和getSingletonPtr(void)函数,这么做是为了避免外界Dll引用这个MyClass发生连接错误:
MyClass* MyClass::getSingletonPtr(void)
{
return ms_Singleton;
}
MyClass & MyClass::getSingleton(void)
{
assert( ms_Singleton ); return ( *ms_Singleton );
}