单件模式(singleton)是很简单的设计模式,一般是为了达到只提供一个类的实例的作用。这里侧重谈实现该模式时的析构函数(针对C++的实现,Java中也没有析构函数这个概念吧)
一般单件模式需要有一个静态的指针来持有(hold/save)这个唯一的实例:
static SingleInst * g_Instance = NULL;
class SingleInst
{
public:
static SingleInst* GetInstance();
private:
SingleInst();
public:
~SingleInst();
};
首先,为类SingleInst提供析构函数是好习惯,并且在大多数情况(当在实例的初始化中分配"额外"的内存时)下是必须的。
那么如何来实现呢?
- SingleInst::~SingleInst()
- {
- // First
- // free the extra memory when call constructor function.
- // Second , anything else
- ......
- // Finally, set the g_Instance to NULL
- g_Instance = NULL;
- }
这是因为 GetInstance()的实现大多如下:
SingleInst* SingleInst::GetInstance()
{
if (g_Instance == NULL)
g_Instance = new SingleInst();
return g_Instance;
}
若在客户程序中有如下的调用顺序:
SingleInst * single = SingleInst::GetInstance(); // 1
/* Do something */
.....
/* Then delete the SingleInst object */ // 2
delete single;
single = NULL;
/* Get the SingleInst object again */ // 3
single = SingleInst::GetInstance();
如果没有析构函数中g_Instance = NULL,那么以上调用顺序就可能会出现问题。例如:
- // Compiler: VC 6.0
- // My Email: cwgk_zc@163.com
- // Date : 2008-08-07
- // If you have any question and suggest about this code
- // segment, please give me a mail.
- #include <iostream.h>
- class SingExm;
- static SingExm * g_instance = NULL;
- class SingExm
- {
- public:
- static SingExm* GetInstance();
- void setValue(int newVal) { *p_iVal = newVal;}
- int getValue() {return *p_iVal;}
- private:
- SingExm() { p_iVal = new int(9); }
- int * p_iVal;
- public:
- ~SingExm();
- };
- SingExm* SingExm::GetInstance()
- {
- if(g_instance)
- return g_instance;
- else
- g_instance = new SingExm();
- return g_instance;
- }
- SingExm::~SingExm()
- {
- // Pay attention to the following line
- g_instance = NULL; // If you delete this line, then you will get a runtime error.
- // You would have a try. (General that error is "access violation" on Windows or
- // "segment fault" on Like-Unix.
- }
- int main()
- {
- SingExm * pSe = SingExm::GetInstance();
- cout<<"Value is"<<pSe->getValue()<<endl;
- pSe->setValue(99);
- cout<<"Value is"<<pSe->getValue()<<endl;
- // Now we delete the pSe
- delete pSe;
- pSe = SingExm::GetInstance();
- cout<<"Value is"<<pSe->getValue()<<endl;
- pSe->setValue(25);
- cout<<"Value is"<<pSe->getValue()<<endl;
- return 0;
- }
总结,一般来讲在单件模式中,实例在程序结束时进行销毁。可是偏偏有一段程序如以上main函数中使用单件模式恰巧让我碰上了,于是有了我这一段文字。(为单件模式提供一个析构函数,并在析构函数中将g_instance设置为NULL)。