單例模式介紹
單例模式(singleton pattern,也稱為單件模式),使用最廣泛的設計模式之一。
單例模式就是乙個類只能被例項化一次 ,更準確的說是只能有乙個例項化的物件的類,該例項被所有程式模組共享。
類似於全域性變數。
有很多地方需要這樣的功能模組,如系統的日誌輸出,gui應用必須是單滑鼠,modem的聯接需要一條且只需要一條**線,作業系統只能有乙個視窗管理器,一台pc連乙個鍵盤等。
使用場景: 實現
通過以上分析,要實現單例模式,需要做到以下幾點:
那麼,單例類的建構函式就要是私有的,可以考慮如下步驟:
初始版本
根據這個思路的實現如下:
// 不完善的類
class
singleton;~
singleton()
;singleton
(const singleton&);
singleton&
operator=(
const singleton&);
private
:static singleton* instance;
public
:static singleton*
getinstance()
};// 初始化靜態成員
singleton* singleton::instance =
null
;
仔細觀察,會發現這個例程只建立了物件,而沒有釋放,存在記憶體洩漏的問題。
有兩種解決辦法:
單執行緒可執行版本
巢狀類物件的實現如下:
// 不完善的類
class
singleton;~
singleton()
;singleton
(const singleton&);
singleton&
operator=(
const singleton&);
private
:static singleton* instance;
private
:class
deletor};
static deletor deletor;
public
:static singleton*
getinstance()
};// 初始化靜態成員
singleton* singleton::instance =
null
;
在程式執行結束時,系統會呼叫靜態成員deletor的析構函式,該析構函式會刪除單例的唯一例項,方法有如下特徵:
這個程式在單執行緒環境下是能夠執行的,但是對於多執行緒,則可能會建立多個例項,如多個執行緒同時進入if (instance == null)
語句。
執行緒安全版本
最簡單的辦法是使用鎖保證執行緒安全,**如下:
static singleton*
getinstance()
return instance;
}
如上的雙檢測鎖模式(dcl: double-checked locking pattern),在保證執行緒安全的情況下又儘量減少對執行效率的影響。
但是,該實現仍然存在問題,設想乙個執行緒執行到了第7行,另乙個執行緒執行到第3行,發現instance已經就緒並返回例項時,然而該例項還未完成構建時,會發生錯誤。
換句話說,就是**中第2行:if(instance == null)和第六行instance = new singleton();沒有正確的同步。
在c++11沒有出來的時候,只能靠插入兩個memory barrier(記憶體屏障)來解決這個錯誤,但是c++11引進了memory model,提供了atomic實現記憶體的同步訪問,即不同執行緒總是獲取物件修改前或修改後的值,無法在物件修改期間獲得該物件。
優雅版本
另外,c++11規定了local static在多執行緒條件下的初始化行為,要求編譯器保證了內部靜態變數的執行緒安全性。
這樣,只有當第一次訪問getinstance()方法時才建立例項。這種方法也被稱為meyers』 singleton。c++0x之後該實現是執行緒安全的,c++0x之前仍需加鎖。
// 完善的類
class
singleton;~
singleton()
;singleton
(const singleton&);
singleton&
operator=(
const singleton&);
public
:static singleton&
getinstance()
};
以上實現在單例例項第一次被使用時才進行初始化,即延遲初始化,稱為懶漢模式(lazy singleton)。
餓漢版餓漢版(eager singleton):指單例例項在程式執行時被立即執行初始化。
// 餓漢版本
class
singleton;~
singleton()
;singleton
(const singleton&);
singleton&
operator=(
const singleton&);
private
:static singleton instance;
public
:static singleton&
getinstance()
};// 預設直接初始化
singleton singleton::instance;
由於在main函式之前初始化,所以沒有執行緒安全的問題。
但是潛在問題在於no-local static物件(函式外的static物件)在不同編譯單元中的初始化順序是未定義的。也即,static singleton instance;和static singleton& getinstance()二者的初始化順序不確定,如果在初始化完成之前呼叫 getinstance() 方法會返回乙個未定義的例項。總結
正因為單例模式使用廣泛,所以在面試中也是最常被問到的問題。
在實際學習中,應結合實際應用使用,學以致用,能夠更加深刻地理解單例模式。
參考資料
c++ 單例模式
C 設計模式之單例模式
在遊戲開發過程中,我們時常會遇到單例模式的運用場景。比如你遊戲當中的最終boss,你希望你的boss只能有乙個,所以這裡你就可以用單例模式 那麼什麼是單例模式呢?看下面的 分析。include include using namespace std class singleton public st...
C 設計模式之單例模式
設計模式是以理論的高度,總結了開發過程中的一多種不同的方法,在各種設計模式中,它們都有著不同實現方式,所起的作用也不相同,我最近看了部分設計模式,主要是以我自己的理解來闡述對它們的看法。我們可以看到單例的大概實現是很簡單的。幾個需要注意的地方是 只有當我們的建構函式為私有時,此時,我們在類外部就不能...
C 設計模式之 單例模式
單例模式,故名思義,其意圖是保證乙個類只有乙個例項,並提供乙個訪問它的全域性訪問點,該例項被所有的程式模組共享.在很多地方要用到這種設計模式,如系統的日誌輸出,作業系統的視窗,乙個pc連乙個鍵盤等.單例模式有許多實現方法.第一次呼叫該類例項的時候才產生乙個新的該類例項,並在以後僅返回此例項,需要加鎖...