目錄
- 1. 什么是單例模式?
- 2. 餓漢
- 3. 懶漢
- 4. 單例模式優缺點
1. 什么是單例模式?
保證一個類僅有一個實體,并提供一個訪問它的全域訪問點,
比較常見的:Windows任務管理器、回收站、系統中的快取等都被設計成了單例模式,這樣既可以避免記憶體資源的浪費、也可以避免因多個視窗顯示不一致等錯誤,
單例模式的本質:控制實體數目;
單例模式是為了控制在運行期間,某些類的實體數目只能有一個;
單例模式有兩種方式實作:餓漢式、懶漢式,
2. 餓漢
餓漢式,顧名思義就是在創建物件實體的時候就比較著急,餓了嘛,就在定義類的時候就創建物件實體;
餓漢式呼叫順序圖:

代碼:
class Signleton
{
public:
static Signleton* GetInstance()//獲取實體,靜態成員函式
{
return &_instance;
}
private:
Signleton(){}
static Signleton _instance;
Signleton(const Signleton&) = delete;//禁掉拷貝構造和賦值運算子多載
Signleton& operator=(const Signleton&) = delete;
};
Signleton Signleton::_instance;//實體化
餓漢式是典型的空間換時間,當類定義的時候就會創建類實體,不管用不用,先創建出來,然后每次呼叫的時候,就不需要再判斷了,節省了運行時間,
3. 懶漢
懶漢式,那么就是在創建實體物件的時候不著急,會一直等到馬上要使用物件實體的時候才會創建,懶人總是在有事情推托不開的時候才會去執行作業;
餓漢式呼叫順序圖:

代碼:
class Signleton
{
public:
static Signleton* GetInstance() noexcept
{
if (_instance == nullptr)
{
_mtx.lock();//上鎖
if (_instance == nullptr)
{
_instance = new Signleton();
}
_mtx.unlock();//解鎖
}
return _instance;//回傳
}
private:
Signleton(){}
static Signleton* _instance;
static mutex _mtx;//互斥鎖
Signleton(const Signleton&) = delete;// 禁掉拷貝構造 和 賦值運算子多載
Signleton& operator=(const Signleton&) = delete;
};
Signleton* Signleton::_instance = nullptr;//初始化
mutex Signleton::_mtx;//互斥鎖
int main()
{
shared_ptr<Signleton> st(Signleton::GetInstance());
//智能指標管理,該實體,避免記憶體泄漏
return 0;
}
為什么需要雙重檢查?
如果在多執行緒環境下,執行緒A此時先走到了if (_instance == nullptr),執行緒B剛好也走到了if (_instance == nullptr),那么執行緒A先執行,new出一個物件,執行緒B再執行,也new出一個物件實體,那么在這樣的情況下,就會new出來兩個物件實體,并且執行緒Anew出來的實體,造成了記憶體泄漏,
第一個if (_instance == nullptr)作用:防止物件已經創建好了,還需要每次加鎖,造成了資源浪費;
第二個if (_instance == nullptr)作用:防止多執行緒時,非原子性操作,導致執行緒切換,實體出多個物件,
懶漢式實作體現了延遲加載的思想:
- 一開始不要加載資源,一直等,等到馬上就要使用這個資源或者資料了,躲不過去才加載,并不是懶惰,是延遲加載,在實際開發中是一種常用的思想,盡可能節約資源,
懶漢式實作還體現了快取的思想:
- 當某些資源或資料頻繁的被使用,而這些資料都在外存上,那么每次操作這些資料的時候都需要從外存上獲取,速度會變慢,造成性能損失;
- 解決方法:將這些資料快取到記憶體里面,每次操作的時候,先到記憶體中去找,看有沒有這些資料,如果有,就直接使用,如果沒有,就獲取該資料,并設定到快取中,下一次訪問的時候,就直接從記憶體中獲取,從而節約大量的時間,
快取是一種典型的空間換取時間的方案,
懶漢式是一種典型的時間換取空間的方案,
4. 單例模式優缺點
一、懶漢式實作需要考慮執行緒安全和釋放的問題,實作相對復雜,餓漢式不存在該問題,實作簡單;
二、懶漢是一種懶加載模式,需要時再初始化創建物件,不會影響程式的啟動;餓漢則相反,程式啟動階段就創建初始化實體物件,會導致程式啟動慢,影響體驗;
三、如果有多個單例類,假設有依賴關系,要求A單例先創建初始化,那么A就不能是餓漢式,有哪位無法保證創建初始化的順序,此時用懶漢就可以手動控制,
實際中,懶漢式更使用一些,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/265441.html
標籤:其他
上一篇:帶你認識清華標桿課教師 | 卓晴:自帶BGM的硬核“技術流”教師
下一篇:Ubuntu18.04+python3.6+pcl-1.8+opencv3+realsense D415環境搭建
