Singleton(单件)模式是一种很常用的设计模式。《Design Patterns》对它作的定义为:Ensure a class only has one instance, and provide a global point of access to it. 也就是说单件类在整个应用程序的生命周期中只能有一个实例存在,使用者通过一个全局的访问点来访问该实例。这是Singleton的两个最基本的特征,也是在实现的时候首先应该考虑的。Singleton的应用很广,它可以典型的被用来表示那些本性上具有唯一特性的系统组件,如数据库访问组件等。这一点在《Design Patterns》上有详细说明,在此就不细说了。
实现Singleton有很多途径,但都离不开两条最基本的原则。首先,要使得Singleton只有一个全局唯一的实例,我们通常的做法是将它的构造函数和拷贝构造函数私有化。再者,Singleton的全局唯一实例通常是一个static变量,这一点利用了语言的内在优势。本文给出的几种实现都比较简单,容易理解。在通常的情况下,它们足以满足要求。但缺点也是不可避免,以下我们逐一分析。
一、基于模板函数的实现
先看实现代码:
class MySingleton1
{
private:
MySingleton1(){ cout << _T("Construct MySingleton1") << endl; }
MySingleton1(const MySingleton1&){} //拷贝构造函数
MySingleton1 & operator =(const MySingleton1&){} //赋值函数
template <typename T>
friend T& GetInstanceRef();
public:
~MySingleton1(){ cout << _T("Destroy MySingleton1") << endl; }
public:
void DoSomething(){ cout << _T("Do something here in MySingleton1") << endl; }
};
template <typename T>
T& GetInstanceRef() //返回全局唯一对象的一个引用
{
static T _instance;
return _instance;
}
template <typename T>
T* GetInstancePtr() //返回全局唯一对象的指针
{
return &GetInstanceRef<T>();
}
上面的代码中,MySingleton1是需要单实例化的类。下面的模板函数template <typename T> T& GetInstanceRef()返回该类的唯一实例(静态变量_instance)的一个引用,另一个模板函数调用它返回该实例的指针。我们可以注意到以下几点:
1. MySingleton1的构造函数私有,防止了程序员随意构造它的实例。
2. 同样,拷贝构造函数MySingleton1(const MySingleton1&)也被声明为私有。
3. 全局的模板函数template <typename T> T& GetInstanceRef()是MySingleton1的友元。因为MySingleton1的构造函数已经声明为私有,为了让GetInstanceRef能顺利的构造静态变量_instance,我们不得不将它声明为MySingleton1的友元函数。
这样,我们的类MySingleton1就具有了Singleton特性了,而全局访问点就是两个模板函数。测试代码如下:
MySingleton1* myobj1;
myobj1 = GetInstancePtr<MySingleton1>();
myobj1->DoSomething();
GetInstanceRef<MySingleton1>().DoSomething();
下面我们分析这种实现的缺点。由于模板函数GetInstanceRef被特化后要访问MySingleton1,它的声明必须在类(MySingleton1)声明之后(区分声明与实现),这与我们通常的使用方式不合。虽然它在其它方面表现的比较良好,但就这一个缺点已经使我不会再想使用它了。来看第二种可以实际使用的实现。
二、基于模板类的实现
这种实现的基本思路是,做一个类让它来负责提供Singleton对象的生成与访问。由于它要构造Singleton对象,所以让它成为一个友元是理所当然的。下面看看实现代码:
template <typename T>
class SingletonWraper
{
public:
static T& GetInstanceRef()
{
static T _instance;
return _instance;
}
static const T& GetInstanceConst()
{
return GetInstanceRef();
}
static T* GetInstancePtr()
{
return &GetInstanceRef();
}
};
#define DEFINE_SINGLETON(ClassName); \
public: \
friend class SingletonWraper<ClassName>; \