单件模式有什么用处,请自行查阅相关书籍:
/* $Log: E/VC/TEST/TESTCONSOLE/JYSINGLETON2.H $ * $Source: /ye/vc/test/testConsole/jySingleton2.h *///$////$ jySingleton2.h//$//$ Author : "Jasper Yeh" <jasperyeh@21cn.com>//$ Version : 1.00.000//$ Create Time : Tuesday, July 31, 200113:59//$ Time-stamp : <Tuesday, July 31, 2001 13:59 jy>//$ Descriptions: (jySingleton2.h 文件的功能描述)//$//$++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//$ If this code works, it was written by Jasper Yeh.//$ If not, I don't know who wrote it.//$//$ Okay, the source code is released for free distribution//$ under the terms of the GNU Lesser GPL License.//$ Lesser GPL is specially at you can reserve your changes//$ on this file(s), no public necessary, but you could be//$ pleasure to notify me by mail.//$ Go to http://www.gnu.org/copyleft/lesser.html for LGPL//$//$//#ifndef __JYSINGLETON2_H#define __JYSINGLETON2_H
#include <memory>#if !defined(JYTRACE)#if defined(_CONSOLE)#define JYTRACE _tprintf#elif defined(_MFC_VER)#define JYTRACE TRACE#else#define JYTRACE #endif#endif
//仍然是一个不算完满的C++解决,但是终于将单件模板化了。
////这里用到的原理是动态中的动态构造模板类的静态成员变量技术:// 1. 模板的代码是在第一次实例化时动态产生的;// 2. 模板类自身的名称的确定也是在第一次实例化时真正具有意义;// 3. 将模板类的静态成员变量放入成员函数体内,解决了放在模板类中声明的尴尬。//例如,这样的代码将会很难使用// template <class T>// class SG {// public:// SG(){}// ~SG(){}// static std::auto_ptr<T> _Tdata;// };//类似的情况主要发生于://a. 一个静态成员变量//b. 该变量的构造依赖于传递来的参数化类名称(即T)//凡是符合上述情况的,都会遇到无法书写该静态变量的实现语句的难题。//例如上例中,为了使用SG模板类,你不得不这样写:// class YY;// typedef SG<YY> SGYY;// std::auto_ptr<YY> SGYY::_Tdata;//horrible!!// SGYY* someptr = new SGYY;//其中,YY是一个已经定义的类。//注意这和标准的模板的用法是有区别的:如果你需要模板化第二个类,你还需要这样写:// class ZZ;// typedef SG<ZZ> SGZZ;// std::auto_ptr<ZZ> SGZZ::_Tdata;//horrible!!// SGZZ* someptr = new SGZZ;//考察上面两段代码的第二句,你可能已经明白问题出在什么地方了。是的,每当需要//参数化一个类的时候,你需要手工的为这个类制作一个模板类SG的静态成员变量的声//明。//如果你不在意这么一句话的开销,可以采用上述的示例,它们已经被证明是有效的。//但是如果你对于封装的意义感到更为重要,或者你的模板类需要多个静态变量的时候,//可能需要参考下面的实现。////这种实现被典型的运用在单件模式上,尤其重要的是,要想利用这种办法,你的模板类//将会是单件式样的。//通过修改// static std::auto_ptr<jySingletonContainer> _Container; ////的声明和具体实现语句,你实际上可以跳脱上述限制,从而允许容器中能够容纳多个实//例(例如,将它声明成一个简单的链表)。//自然,Instance()函数本身的声明也需要调整以适应多个实例的情况。////由于模板类这时候的功能已经演变为包容一个或者多个参数类的指针了,因此,我们使//用了jySingletnContainer这样的名字,以便强调一下他的容器特性。////顺便一提,auto_ptr<jySingleton<T>> _Container;的语法是不容易通过的。
template <class T>class jySingleton{ //为了运用jySingleton<T>,你需要: // 不能从参数类直接构造其实例,只能通过jySingleton<T>::Instance()来取得和 //运用参数类的的实例。标准实例如下: // class YY; // typedef jySIngleton<YY> CYY; // YY* pyy = *CYY::Instance();//灵巧指针机制使得CYY的实例指针不必被关注 jySingleton(){ _Ptr = NULL; JYTRACE(_T("jySingleton<T> class initializing at %p/n"), this); }public: ~jySingleton(){ release(); JYTRACE(_T("jySingleton<T> class at %p deconstructing/n"), this); }public: typedef jySingleton<T> jySingletonContainer;
//**************************************************************** //只能使用这个接口来获取T的实例的指针 //至于jySingleton<T>容器类自身的那个唯一实例的指针,反而不必再予 //以考虑了。 static jySingleton<T>* Instance(){ // //singleton class me (i.e. jySingleton<T>) //Error syntax: // static std::auto_ptr<jySingleton<T>> _Container; // static std::auto_ptr<jySingletonContainer> _Container;
if(_Container.get()==NULL){ jySingletonContainer* sg = new jySingletonContainer(); sg->_Ptr = new T;
_Container = std::auto_ptr<jySingletonContainer>(sg); }
return _Container.get(); }
public: operator T*(){ return get(); }
T* operator ->() {return get(); } T& operator *() {return *get();} T* get(){ return _Ptr; }
void release(){ if(_Ptr){delete _Ptr;_Ptr=NULL;} } T* detach(){ T* p=_Ptr;_Ptr=NULL; return p; }
private: T* _Ptr; //T类的一个工作副本,以便客户能够使用。无论那种情况,一个副本。};
#endif //__JYSINGLETON2_H
下一篇文章将讲述传统的单件在C++中怎样实现是最优的。