設計模式之單例模式
時間:2020-08-19 00:47:26
手機看文章
掃描二維碼
隨時隨地手機看文章
[導讀]程序喵最近開始系統(tǒng)學習回顧設計模式,希望能把學到的東西分享給大家,今天總結(jié)下創(chuàng)建型模式中最經(jīng)典的單例模式。 “ ?? 什 么 是 單 例 模 式 ? ?” 這里首先介紹下什么是創(chuàng)建型模式,創(chuàng)建型模式主要解決對象的創(chuàng)建過程,封裝對象復雜的創(chuàng)建過程,解耦對象
程序喵最近開始系統(tǒng)學習回顧設計模式,希望能把學到的東西分享給大家,今天總結(jié)下創(chuàng)建型模式中最經(jīng)典的單例模式。
而單例模式指的就是在系統(tǒng)里一個類只能產(chǎn)生一個實例,確保全局唯一。
“
懶 漢 式 實 現(xiàn) 1
”
class Singleton {
public:
static Singleton *GetInstance();
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部構造對象,想拿到類的實例只能通過GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton *instance_;
static std::mutex mutex_;
};
Singleton *Singleton::instance_ = nullptr;
std::mutex Singleton::mutex_;
Singleton *Singleton::GetInstance() {
// double check
if (instance_ == nullptr) { // 1
std::unique_lock<std::mutex> lock(mutex_);
if (instance_ == nullptr) { // 2
instance_ = new Singleton();
}
}
return instance_;
}
int main() {
Singleton::GetInstance()->Func();
return 0;
}
為什么需要加鎖?加鎖的原因很簡單,為了確保線程安全。
您看過代碼可能也有些疑惑,明明加一次鎖和第二次的判斷就足夠了,為什么在加鎖之前還需要進行一次判斷呢?這里可以考慮只需要在判斷指針為空的時候才去加鎖,避免每次調(diào)用方法時都加鎖,可以減少加鎖解鎖帶來的額外開銷。
這里需要將類的構造函數(shù)和拷貝構造函數(shù)等設成私有函數(shù),避免外部構造類的實例,防止外部通過new關鍵字進行實例化。
“
懶 漢 式 實 現(xiàn) 2
”
class Singleton {
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部構造對象,想拿到類的實例只能通過GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
int main() {
Singleton::GetInstance().Func();
return 0;
}
“
餓 漢 式 實 現(xiàn)
”
class Singleton {
public:
static Singleton *GetInstance();
void Func() { std::cout << "Singleton Func \n"; }
private:
Singleton() {} // 避免外部構造對象,想拿到類的實例只能通過GetInstance()
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton *instance_;
};
Singleton *Singleton::instance_ = new Singleton();
Singleton *Singleton::GetInstance() {
return instance_;
}
int main() {
Singleton::GetInstance()->Func();
return 0;
}
“
std::call_once實現(xiàn) ”
template <typename T>
class SingleTon {
public:
static T& instance() {
std::call_once(once_, &SingleTon::init);
return *value_;
}
private:
SingleTon();
~SingleTon();
SingleTon(const SingleTon&) = delete;
SingleTon& operator=(const SingleTon&) = delete;
static void init() { value_ = new T(); }
static T* value_;
static std::once_flag once_;
};
總結(jié)
-
類只能有一個實例。 -
外部用戶不能也無法自行對類進行實例化,實例化的操作需要類內(nèi)部去實現(xiàn)。 -
整個進程共用一個類的實例,且需要是線程安全的。
往期推薦
免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!