Singleton模式的析構函數

單件模式(singleton)是很簡單的設計模式,一般是爲了達到只提供一個類的實例的作用。這裏側重談實現該模式時的析構函數(針對C++的實現,Java中也沒有析構函數這個概念吧)

一般單件模式需要有一個靜態的指針來持有(hold/save)這個唯一的實例:

static SingleInst * g_Instance = NULL;

class  SingleInst
{
public:
 static SingleInst* GetInstance();
private:
 SingleInst();
public:
 ~SingleInst();
};

首先,爲類SingleInst提供析構函數是好習慣,並且在大多數情況(當在實例的初始化中分配"額外"的內存時)下是必須的。

那麼如何來實現呢?

  1. SingleInst::~SingleInst()
  2. {
  3.  // First  
  4.  // free the extra memory when call constructor function.
  5.  // Second , anything else
  6. ......
  7.  // Finally, set the g_Instance to NULL
  8.  g_Instance  =  NULL;
  9. }

這是因爲 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,那麼以上調用順序就可能會出現問題。例如:

 

  1. // Compiler: VC 6.0
  2. // My Email: [email protected]
  3. // Date    : 2008-08-07
  4. // If you have any question and suggest about this code
  5. // segment, please give me a mail.
  6. #include <iostream.h>
  7. class SingExm;
  8. static SingExm * g_instance = NULL;
  9. class  SingExm
  10. {
  11. public:
  12.  static SingExm* GetInstance();
  13.  void setValue(int newVal) { *p_iVal = newVal;}
  14.  int getValue() {return *p_iVal;}
  15. private:
  16.  SingExm() { p_iVal = new int(9); }
  17.  int     * p_iVal;
  18. public:
  19.  ~SingExm();
  20. };
  21. SingExm* SingExm::GetInstance()
  22. {
  23.  if(g_instance)
  24.   return g_instance;
  25.  else
  26.   g_instance = new SingExm();
  27.  return g_instance;
  28. }
  29. SingExm::~SingExm()
  30. {
  31.  // Pay attention to the following line
  32.  g_instance = NULL; // If you delete this line, then you will get a runtime error.
  33.         // You would have a try. (General that error is "access violation" on Windows or
  34.         // "segment fault" on Like-Unix.
  35. }
  36. int main()
  37. {
  38.  SingExm * pSe = SingExm::GetInstance();
  39.  cout<<"Value is"<<pSe->getValue()<<endl;
  40.  pSe->setValue(99);
  41.  cout<<"Value is"<<pSe->getValue()<<endl;
  42.  // Now we delete the pSe
  43.  delete pSe;
  44.  pSe = SingExm::GetInstance();
  45.  cout<<"Value is"<<pSe->getValue()<<endl;
  46.  pSe->setValue(25);
  47.  cout<<"Value is"<<pSe->getValue()<<endl;
  48.  return 0;
  49. }

總結,一般來講在單件模式中,實例在程序結束時進行銷燬。可是偏偏有一段程序如以上main函數中使用單件模式恰巧讓我碰上了,於是有了我這一段文字。(爲單件模式提供一個析構函數,並在析構函數中將g_instance設置爲NULL)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章