單件模式(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: [email protected]
- // 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)。