Singleton Pattern 是软件设计中比较常用到的一个模式,有些时候需要将多个class都设计为Singleton,那除了copy and paste之外,还有啥更好的方法呢?C++ Template机制就提供了一个很好的手段。如下代码就是这样的一种实现,compiled and tested with Linux 2.6.18 and gcc 4.1.1
//TemplateSingleton.cpp
//please compile with g++ TemplateSingleton -lpthread
#include <iostream>
#include <pthread.h>
using namespace std;
template <class T>
class Singleton
{
protected:
Singleton();
public:
static T* t_;
static pthread_mutex_t m_; //Each template class or function generated from a template has its own copies of any static variables or members.
static T* getInstance();
};
class C1
{
friend class Singleton<C1>;
protected:
C1() {cout << "C1 constructor" << endl;}
~C1() {cout << "C1 destructor" << endl;}
};
class C2
{
friend class Singleton<C2>;
protected:
C2() {cout << "C2 constructor" << endl;}
~C2() {cout << "C2 destructor" << endl;}
};
template <class T> T* Singleton<T>::t_ = 0;
template <class T> pthread_mutex_t Singleton<T>::m_;
template <class T> T* Singleton<T>::getInstance()
{
if (t_ == 0) //try to comment out this line and the line with pthread_mutex_unlock to confirm that m_ is not shared by Singleton<C1> and Singleton<C2>
{
pthread_mutex_lock(&m_);
if (t_ == 0)
t_ = new T;
pthread_mutex_unlock(&m_);
}
return t_;
}
int main(void)
{
{
C1* c1 = Singleton<C1>::getInstance();
C2* c2 = Singleton<C2>::getInstance();
cout << "c1 address: 0x" << hex << &c1 << dec << endl;
cout << "c2 address: 0x" << hex << &c2 << dec << endl;
cout << "c1 points to: 0x" << hex << c1 << dec << endl;
cout << "c2 points to: 0x" << hex << c2 << dec << endl;
// delete c1; //C1 is protected for construction and destruction
}
{
C1* c3 = Singleton<C1>::getInstance();
C2* c4 = Singleton<C2>::getInstance();
cout << "c3 address: 0x" << hex << &c3 << dec << endl;
cout << "c4 address: 0x" << hex << &c4 << dec << endl;
cout << "c3 points to: 0x" << hex << c3 << dec << endl;
cout << "c4 points to: 0x" << hex << c4 << dec << endl;
}
}
有了Singleton class 之后,其他真正想实现为Singleton Pattern的class就不用再考虑和该pattern相关的逻辑了,只需要在常规class定义的基础上做出如下改动
1。 申明构造函数为protected
2. 申明友元friend class Singleton<ClassName>;
在需要用到Singleton Instance的地方,只要作如下调用即可
ClassName* c1 = Singleton<ClassName>::getInstance();