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

2021-09-25 04:36:45 字數 3195 閱讀 8717

單例模式介紹

單例模式(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連乙個鍵盤等.單例模式有許多實現方法.第一次呼叫該類例項的時候才產生乙個新的該類例項,並在以後僅返回此例項,需要加鎖...