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