設計模式之單例模式(singleton模式)


筆者工作中第一次遇到的模式就是單例模式了,單例模式簡單好用,但是極容易被濫用,尤其在小型系統中。


WIKI是這麼解釋單例模式的,我個人覺得很精確。

單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行爲。比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在複雜環境下的配置管理。

實現單例模式的思路是:一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常使用getInstance這個名稱);當我們調用這個方法時,如果類持有的引用不爲空就返回這個引用,如果類保持的引用爲空就創建該類的實例並將實例的引用賦予該類保持的引用;同時我們還將該類的構造函數定義爲私有方法,這樣其他處的代碼就無法通過調用該類的構造函數來實例化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一實例。

單例模式在多線程的應用場合下必須小心使用。如果當唯一實例尚未創建時,有兩個線程同時調用創建方法,那麼它們同時沒有檢測到唯一實例的存在,從而同時各自創建了一個實例,這樣就有兩個實例被構造出來,從而違反了單例模式中實例唯一的原則。 解決這個問題的辦法是爲指示類是否已經實例化的變量提供一個互斥鎖(雖然這樣會降低效率)。


在實際的項目中,我是這樣做的: 


實現一個單例的模板:


template<typename T>
class USingletonTemplate
{
public:
// Get the object.
static T& GetInstance() 
{
if (_instance == NULL)
{


Project::Tools::Scoped_Lock<Project::Tools::Mutex> lock(mutex);
if (_instance == NULL)
{
_instance = new T();
atexit(Destroy);
}
}


return *_instance;
}


protected:
USingletonTemplate() {};
// destructor
~USingletonTemplate(){};
private:
// constructor


USingletonTemplate(const USingletonTemplate&);
USingletonTemplate& operator=(const USingletonTemplate&);


static void Destroy()
{
if (_instance != NULL)
{
delete _instance;
_instance = NULL;
}
}
// data members
static Project::Tools::Mutex mutex;
static T* volatile _instance;
};


template<typename T>
Project::Tools::Mutex USingletonTemplate<T>::mutex;


template<typename T>
T* volatile USingletonTemplate<T>::_instance= NULL;


其中mutex自己封裝的互斥信號量,scopelock是局部的自動鎖,構造時加鎖,析構時釋放鎖


定義一個新模板的single類時,只需要這樣繼承

Class A : Public USingletonTemplate<A>

{

.......

}

這樣類A就是默認singleton的了


singleton的實現核心在getsintance這個函數裏。裏面的細節很多人都有文章介紹過了,主要就是要

採用雙重枷鎖機制,也就是本例子採用的例子,用來保證線程安全。


更詳細的信息見:

http://calmness.iteye.com/blog/60179


個人建議這個模式能不用就不用。主要原因如下:

1. 無法保證類的創建和析構時間,你無法保證析構函數的執行時間。這對於某些資源的釋放,是一個很大的難題。

2. 多線程問題,這個問題是可以避免的,

3. 容易造成系統的設計混亂。我個人認爲濫用單例模式是反模式的,單例的類就是一個一個的孤島,會影響到

系統中類與類之間的關係。




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