单体模式+模板类+智能指针实现CSingleton

时间:2022-04-04 19:51:08

定义

单体(Singleton)模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。

 

理解

1.       Singleton模式用来取代全局静态变量。C++通过静态成员变量来实现类实例全局唯一性。

2.       instance()方法是单体提供的唯一调用入口。

 

要点

1.       为了防止外界调用产生多个实例,将构造方法、析构方法、拷贝构造方法、赋值重载方法都作为private/protected

2.       instance()方法产生对象方式有两种:使用局部static对象,生命期在首次进入局部生命期产生,在程序结束时销毁;通过new产生新对象,在析构方法中delete对象。

3.       获取单体实例调用方式:Singleton::instance()获取对象指针。

4.       解决多线程资源竞争条件。使用著名的“双检测锁定”办法来解决,即在锁定前和锁定后都检测对象是否产生,这样既能保证加锁效率又能保证单件实例的唯一性。

 

应用

1.       代码部分使用类模版单体(CSingleton<T>),可产生不同种类的单件类。

2.       一个类要成为单体类,把单体类作为自己的友元来实现。因为CSingleton的构造和析构都是private/protected。另外也有通过继承单体来实现。


template <class T>
class CSingleton
{
public:
static inline T* Instance();
private:
CSingleton(void){}
~CSingleton(void){}

CSingleton(const CSingleton&){}
CSingleton & operator= (const CSingleton &){}

static auto_ptr<T> _instance;
static CQuickLock _rs;
};

template <class T>
auto_ptr<T> CSingleton<T>::_instance;

template <class T>
CQuickLock CSingleton<T>::_rs;

/**************************************************************************
Function: Instance
Description: get singleton object
Input:
Output: -
Return: - T*
Others: -
**************************************************************************/
template <class T>
inline T* CSingleton<T>::Instance()
{

if( 0 == _instance.get() )
{
//CScopedLock lock(_rs);
if( 0== _instance.get())
{
_instance.reset ( new T);
}
}
return _instance.get();
}

/////////////////Singleton应用实例class CMyLog{friend class auto_ptr<CMyLog>;   //作为友元可以访问CMyLog的私有成员friend class CSingleton<CMyLog>; //作为友元可以访问CMyLog的私有成员 public:    void Log(char* pszStr)    {        cout << "Log msg: " << pszStr << endl;    } private:    CMyLog(){}; //不允许直接实例化
    virtual ~CMyLog(void);}; int main(){    CMyLog* pLog = CSingleton<CMyLog>::Instance();    pLog->Log("hello word");     system("pause");    return 0;}
 


备注:

1、智能指针auto_ptr是一个模板类 ,适合于任何类型。主要是为了解决“被异常抛出时发生资源泄漏”的问题。即使在函数执行过程时发生异常退出,也会因为异常能保证局部对象被析构从而保证资源被释放。 

我们定义一个智能指针,就是定义了一个auto_ptr类的对象,如:auto_ptr<string> p (new string); 
这句话就定义了一个auto_ptr类的对象p,尖括号里面的string用来初始化它的模板成员_Ty的类型。那么这里面,只要auto_ptr对象存在,它指向的字符串就存在,同理,如果auto_ptr对象不存在,auto_ptr类中的析构函数自动销毁它所指向的字符串,也就避免了内存泄露。

2、friend class auto_ptr<CMyLog>;
说明auto_ptr类是CMyLog类的友元类,在auto_ptr中可以访问CMyLog类的私有成员。为了在智能指针析构的时候可以调用CMyLog类的私有析构函数

3、friend class CSingleton< CMyLog>;
说明CSingleton单体类是CMyLog类的友元类,在CSingleton中可以访问CMyLog类的私有成员。为了在单体类中创建CMyLog时候可以调用CMyLog类的私有构造函数

4、static auto_ptr<T> _instance;
CSingleton< CMyLog>; ,类型参数T为CMyLog,CSingleton类中static auto_ptr< CMyLog> _instance;
 _instance.reset ( new CMyLog ) ;
智能指针指向CMyLog的对象,智能指针释放时会调用CMyLog的析构函数。(正常情况下这个静态的智能指针在程序退出时释放)