除了用静态成员的方法保证单例,也可以用一个类变量记录实例对象指针来保存生成的实例。
#ifndef _BATS_SINGLETON_HH_
#define _BATS_SINGLETON_HH_
#include <stdexcept>
namespace jmu3d
{
/**
* A template to turn any class into a Singleton. To use it on your class:
* - Define your class's constructor and assignment operator as private
* - Your class must have a default constructor
* - Make the singleton a friend of your class.
* - If your class needs parameters, overload the Params class, define a constructor accepting a Singleton::Params* and use Singleton<T>::initialize<I>(Params*)
*
* Example:
* \code
class MyClass
{
friend class Singleton<MyClass>;
...
private:
MyClass();
MyClass& operator=(MyClass const& other); // Not Implemented
...
};
\endcode
*/
template <typename T>
class Singleton
{
public:
class Params
{
public:
virtual ~Params() {}
};
/** Initialize the singleton with a new instance of the given type.
*/
static void initialize()
{
if (s_instance)
delete s_instance;
s_instance = new T();
}
/** Initialize the singleton with a new instance of the given type with parameters
* @params parameters to be passed to the classes construction
*/
static void initialize(Params* params)
{
if (s_instance)
delete s_instance;
s_instance = new T(params);
}
/** Initialize the singleton with a new instance of the given derived class type.
* With this method, it is possible to create different derived class type from
* same abstract singleton type.
*/
template <typename I>
static void initialize()
{
if(s_instance)
delete s_instance;
s_instance = new I();
}
/** Initialize the singleton with a new instance of the given type with parameters
* With this method, it is possible to create different derived class type from
* same abstract singleton type.
* @params parameters to be passed to the classes construction
*/
template <typename I>
static void initialize(Params *params)
{
if(s_instance)
delete s_instance;
s_instance = new I(params);
}
static bool initialized()
{
return s_instance? true : false;
}
/**
* Get a reference to the only instance of class \a T
*/
static T& getInstance() {
if(s_instance == 0)
throw std::runtime_error("A Singleton must be initialized before use. Call initialize first.");
return *s_instance;
}
private:
static T* s_instance;
Singleton();
~Singleton();
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
};
template <typename T>
T* Singleton<T>::s_instance = 0;
}
#endif
s_instance 指针决定了是否已经有实例,设置成静态的是因为要在静态函数里面调用,设计成私有是因为如果它是公有可能会被改变,这样实例就被破坏了~~