c++設計模式:單件模式(Singleton Pattern)


定義:單件模式確保一個類只有一個實例,並提供一個全局訪問點

實現一:

#include <iostream>
using namespace std;

class CSingleton
{
public:
static CSingleton* getInstance();
static void cleanInstance();
int getValue();
void setValue(int iValue);
private:
int m_iValue;
static CSingleton* m_pSingleton;
CSingleton();
~CSingleton();
};

CSingleton* CSingleton::m_pSingleton = NULL;

CSingleton::CSingleton()
{
cout << "Constructor" << endl;
}

CSingleton::~CSingleton()
{
cout << "Destructor" << endl;
}

CSingleton* CSingleton::getInstance()
{
if (NULL == m_pSingleton)
{
m_pSingleton = new CSingleton();
}
return m_pSingleton;
}

void CSingleton::cleanInstance()
{
delete m_pSingleton;
}

int CSingleton::getValue()
{
return m_iValue;
}

void CSingleton::setValue(int iValue)
{
m_iValue = iValue;
}

int main()
{
CSingleton* pSingleton1 = CSingleton::getInstance();
CSingleton* pSingleton2 = CSingleton::getInstance();
pSingleton1->setValue(123);
if (pSingleton1->getValue() == pSingleton2->getValue())
{
cout << "Two objects is the same instance" << endl;
}
else
{
cout << "Two objects isn't the same instance" << endl;
}

CSingleton::cleanInstance();
return 0;
}

相信大多數的同仁都喜歡使用上邊這種單件模式的實現方法,如果在單線程的情況下,是沒有問題的,但如果是多線程,那么就極有可能會返回兩個不同的對象,在調用

CSingleton::getInstance的時候,兩個線程如果都同時運行完if判斷,而又還沒有調用到構造函數的話,想象下后果吧。那該怎么辦呢?看下邊這個實現吧。
實現二:
#include <iostream>
using namespace std;

class CSingleton
{
public:
static CSingleton* getInstance();
static void cleanInstance();
int getValue();
void setValue(int iValue);
private:
int m_iValue;
static CSingleton* m_pSingleton;
CSingleton();
~CSingleton();
};

// 在進程運行開始就實例化該單件,又稱“急切”創建實例
CSingleton* CSingleton::m_pSingleton = new CSingleton();

CSingleton::CSingleton()
{
cout << "Constructor" << endl;
}

CSingleton::~CSingleton()
{
cout << "Destructor" << endl;
}

CSingleton* CSingleton::getInstance()
{
return m_pSingleton;
}

void CSingleton::cleanInstance()
{
delete m_pSingleton;
}

int CSingleton::getValue()
{
return m_iValue;
}

void CSingleton::setValue(int iValue)
{
m_iValue = iValue;
}

int main()
{
CSingleton* pSingleton1 = CSingleton::getInstance();
CSingleton* pSingleton2 = CSingleton::getInstance();
pSingleton1->setValue(123);
if (pSingleton1->getValue() == pSingleton2->getValue())
{
cout << "Two objects is the same instance" << endl;
}
else
{
cout << "Two objects isn't the same instance" << endl;
}

CSingleton::cleanInstance();
return 0;
}
哈哈,看清楚了嗎?就是在進程運行的時候就對這個單件進行實例化,可是這樣似乎又不能達到延遲實例化的目的啦。如果我們的對象對資源占用非常大,而我們的進行在整個過程中其實並沒有用到這個單件,那豈不是白白浪費資源了嘛。還有更好的辦法。
實現三:
#include <iostream>
using namespace std;

class CSingleton
{
public:
static CSingleton* getInstance();
int getValue();
void setValue(int iValue);
private:
int m_iValue;
CSingleton();
~CSingleton();
};

CSingleton::CSingleton()
{
cout << "Constructor" << endl;
}

CSingleton::~CSingleton()
{
cout << "Destructor" << endl;
}

CSingleton* CSingleton::getInstance()
{
static CSingleton single;
return &single;
}

int CSingleton::getValue()
{
return m_iValue;
}

void CSingleton::setValue(int iValue)
{
m_iValue = iValue;
}

int main()
{
cout << "Process begin" << endl;
CSingleton* pSingleton1 = CSingleton::getInstance();
CSingleton* pSingleton2 = CSingleton::getInstance();
pSingleton1->setValue(123);
if (pSingleton1->getValue() == pSingleton2->getValue())
{
cout << "Two objects is the same instance" << endl;
}
else
{
cout << "Two objects isn't the same instance" << endl;
}
return 0;
}
看下運行結果吧:

Process begin
Constructor
Two objects is the same instance
Destructor

是不是跟預想的一樣呢?把單件聲明為成員函數中的靜態成員,這樣既可以達到延遲實例化的目的,又能達到線程安全的目的,而且看結果的最后,是不是在程序退出的時候,還自動的調用了析構函數呢?這樣我們就可以把資源的釋放放到析構函數里邊,等到程序退出的時候,進程會自動釋放這些靜態成員的。

 
參考圖書:《Head First 設計模式》




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM