設計模式--單例模式: 創建一個安全並且高效的Sington很重要。 (1)單例類保證全局只有一個唯一實例對象; (2)單例類提供獲取這個唯一實例的接口。 下面爲四種創建單例類的方法: //單例模式 ////////不考慮線程安全的單例類////////// class Singleton { public: //獲取唯一對象實例的接口函數 static Singleton * GetIntance() { if (_sIntance == NULL ) { if (_sIntance == NULL ) { _sIntance = new Singleton (); } } return _sIntance; } //刪除實例對象 static void DelIntance() { if (_sIntance) { delete _sIntance; _sIntance = NULL; } } void Print() { cout << _data << endl; } private: //構造函數定義爲私有,限制只能在類內創建對象 Singleton() :_data(0) {} //防拷貝 Singleton( const Singleton &); Singleton& operator=(const Singleton&); private: static Singleton * _sIntance;//指向實例的指針定義爲靜態私有,定義靜態函數獲取實例對象 int _data;//單例類裏的數據 }; Singleton* Singleton ::_sIntance = NULL; //靜態成員只能在類外初始化 void TestSingleton() { Singleton::GetIntance()->Print(); Singleton::DelIntance(); }
////////////線程安全的單例模式(懶漢模式)//////////// class Singleton { public: //獲取唯一對象實例的接口函數 static Singleton * GetIntance() { //使用雙重檢查,提高效率,避免高併發場景下每次獲得實例對象都進行加鎖,浪費資源 if (_sIntance == NULL ) { std:: lock_guard<std::mutex > lck(_mtx); if (_sIntance == NULL ) { Singleton* tmp = new Singleton(); MemoryBarrier(); //內存柵欄,防止編譯器重排柵欄後的賦值到柵欄之前 _sIntance = tmp; } } return _sIntance; } //刪除實例對象 static void DelIntance() { std:: lock_guard<std::mutex > lck(_mtx); if (_sIntance) { delete _sIntance; _sIntance = NULL; } } void Print() { cout << _data << endl; } private: //構造函數定義爲私有,限制只能在類內創建對象 Singleton() :_data(0) {} //防拷貝 Singleton( const Singleton &); Singleton& operator=(const Singleton&); private: static mutex _mtx;//保證線程安全的互斥鎖 static Singleton * _sIntance;//指向實例的指針定義爲靜態私有,定義靜態函數獲取實例對象 int _data;//單例類裏的數據 }; Singleton* Singleton ::_sIntance = NULL; //靜態成員只能在類外初始化 mutex Singleton::_mtx; void TestSingleton() { Singleton::GetIntance()->Print(); Singleton::DelIntance(); }
/////////////餓漢模式(簡潔,不加鎖)///////////////////////// class Singleton { public: //獲取唯一對象實例的接口函數 static Singleton * GetIntance() { static Singleton sIntance; return &sIntance; } void Print() { cout << _data << endl; } private: //構造函數定義爲私有,限制只能在類內創建對象 Singleton() :_data(0) {} //防拷貝 Singleton( const Singleton &); Singleton& operator=(const Singleton&); private: int _data;//單例類裏的數據 }; void TestSingleton() { Singleton::GetIntance()->Print(); } ////////// /////餓漢模式2//////////////////// class Singleton { public: //獲取唯一對象實例的接口函數 static Singleton *GetIntance() { assert(_sIntance); return _sIntance; } //刪除實例對象 static void DelIntance() { if (_sIntance) { delete _sIntance; _sIntance = NULL; } } void Print() { cout << _data << endl; } private: //構造函數定義爲私有,限制只能在類內創建對象 Singleton() :_data(0) {} //防拷貝 Singleton( const Singleton &); Singleton& operator=(const Singleton&); private: static Singleton * _sIntance;//指向實例的指針定義爲靜態私有,定義靜態函數獲取實例對象 int _data;//單例類裏的數據 }; Singleton* Singleton ::_sIntance = new Singleton; //靜態成員只能在類外初始化 void TestSingleton() { Singleton::GetIntance()->Print(); Singleton::DelIntance(); }
///////////////使用RAII GC自動回收實例對象的方式/////////// class Singleton { public: //獲取唯一對象實例的接口函數 static Singleton * GetIntance() { assert(_sIntance); return _sIntance; } //刪除實例對象 static void DelIntance() { if (_sIntance) { delete _sIntance; _sIntance = NULL; } } void Print() { cout << _data << endl; } class GC { public: ~GC() { cout << "DelIntance" << endl; DelIntance(); } }; private: //構造函數定義爲私有,限制只能在類內創建對象 Singleton() :_data(0) {} //防拷貝 Singleton( const Singleton &); Singleton& operator=(const Singleton&); private: static Singleton * _sIntance;//指向實例的指針定義爲靜態私有,定義靜態函數獲取實例對象 int _data;//單例類裏的數據 }; Singleton* Singleton ::_sIntance = new Singleton; //靜態成員只能在類外初始化 //使用RAII,定義全局的GC對象釋放對象實例 Singleton::GC gc; void TestSingleton() { Singleton::GetIntance()->Print(); }