設計模式 單例模式 Singleton

2021-10-05 11:08:29 字數 3936 閱讀 9709

2. 單例模式的實現

3. 致謝

單例模式:保證乙個類僅有乙個例項,並提供乙個訪問他的全域性訪問點。[dp]

通常我們可以定義乙個全域性變數使得物件被訪問,但它不能防止你例項化多個物件。乙個最好的方法就是,讓類自身負責儲存它的唯一例項。這個類可以保證沒有其他例項可以被建立,並且它可以提供乙個訪問該類例項的方法。

單例模式的實現分為懶漢式和餓漢式:

運用場景舉例如下:

裝置管理器,系統中可能有多個裝置,但是只有乙個裝置管理器,用於管理裝置驅動;

資料池,用來快取資料的資料結構,需要在一處寫,多處讀取或者多處寫,多處讀取。

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:static singleton*

getinstance()

return m_pinstance;

}private

:static singleton* m_pinstance;};

singleton* singleton::m_pinstance =

nullptr

;

上述懶漢式模式存在的問題:

針對上述問題,第一條我們可以通過加鎖解決,第二條我們可以通過使用智慧型指標來解決。因此有了以下實現。

#include

#include

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:static std::shared_ptr

getinstance()

}return m_pinstance;

}private

:static std::shared_ptr m_pinstance;

static std::mutex m_mutex;};

std::shared_ptr singleton::m_pinstance =

nullptr

;std::mutex singleton::m_mutex;

上述方式也還是有問題的,使用了智慧型指標要求使用者也使用智慧型指標,這可以通過從智慧型指標中獲取原始指標並返回原始指標來解決,但是,必須保證使用者在外部不要呼叫delete,且不再用智慧型指標二次包裝原始指標,否則也會引發問題。

另外,在某些平台(與編譯器和指令集架構有關),雙檢鎖會失效!

針對上述問題,結合c++11特性,有了以下實現。

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:static singleton&

getinstance()

};

上述**一次解決了多執行緒問題,記憶體安全問題,並且利用c++靜態變數的生存期是從宣告開始到程式結束的特性。該方式是最推薦方式。

餓漢式的實現相對簡單,**如下:

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:static singleton&

getinstance()

private

:static singleton m_instance;};

singleton singleton::m_instance;

上述實現方式在類載入時初始化例項物件,並直到程式結束,不管使用者需要還是不需要該單例,稱為餓漢式單例,增加了記憶體占用,是一種以空間換時間的方式。

template

<

typename t>

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:virtual

~singleton()

static t&

getinstance()

};class

derivedsingle

:public singleton

derivedsingle

(const derivedsingle&)=

delete

; derivedsingle&

operator=(

const derivedsingle&)=

delete;}

;int

main

(int argc,

char

* ar**)

上述**需要在子類中將基類宣告為友元,這樣才能呼叫子類的私有建構函式,使用起來較為不便。在 stackoverflow上, 有大神給出了不需要在子類中宣告友元的方法,在這裡一併放出;精髓在於使用乙個**類 token,子類建構函式需要傳遞token類才能構造,但是把 token保護其起來, 然後子類的建構函式就可以是公有的了,這個子類只有 derived(token)的這樣的建構函式,這樣使用者就無法自己定義乙個類的例項了,起到控制其唯一性的作用。改進如下:

template

<

typename t>

class

singleton

singleton

(const singleton&)=

delete

; singleton&

operator=(

const singleton&)=

delete

;public

:virtual

~singleton()

static t&

getinstance()

;return instance;

}protected

:struct token ;}

;class

derivedsingle

:public singleton

derivedsingle

(const derivedsingle&)=

delete

; derivedsingle&

operator=(

const derivedsingle&)=

delete;}

;int

main

(int argc,

char

* ar**)

Java設計模式之單例模式(Singleton)

前言 在總結okhttp的時候,為了管理網路請求使用到了單例模式,晚上實在沒啥狀態了,靜下心來學習總結一下使用頻率最高的設計模式單例模式。單例模式 單例模式確保某個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。單例特點 單例分類 1 懶漢單例 1 非執行緒安全實現 public class...

設計模式 建立型模式 單例模式 Singleton

4種單例模式 單執行緒單例 類class single private static single sin null public static single createinstance return sin 呼叫 console.writeline 單執行緒單例模式 single sin sin...

大話設計模式二十一 單例模式(Singleton)

一.單例模式定義 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。二.結構和說明 singleton負責建立singleton類自己的唯一例項,並提供乙個getinstance方法,讓外部來訪問這個類的唯一例項。三.呼叫示例圖 實現 四.控制例項個數 簡單演示如何擴充套件單例模式,控制例項數...