設計模式是對設計原則的具體化。用江湖話說就是武林祕籍,總結出來的一些固定套路,可以幫助有根基的程序員迅速打通任督二脈,從此做什麼都特別快。
單例模式
單例模式是一種常用的軟件設計模式。
在它的核心結構中只包含一個被稱爲單例類的特殊類。通過單例模式可以保證系統中一個類只有一個實例而且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。
應用場景:如果希望在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。
實現單例模式必須注意一下幾點:
● 單例類只能由一個實例化對象。
● 單例類必須自己提供一個實例化對象。
● 單例類必須提供一個可以訪問唯一實例化對象的接口。
單例模式分爲懶漢和餓漢兩種實現方式。
懶漢單例模式
懶漢:故名思義,不到萬不得已就不會去實例化類,也就是說在第一次用到類實例的時候纔會去實例化一個對象。在訪問量較小,甚至可能不會去訪問的情況下,採用懶漢實現,這是以時間換空間。
非線程安全的懶漢單例模式
/*
* 關鍵代碼:構造函數是私有的,不能通過賦值運算,拷貝構造等方式實例化對象。
*/
//懶漢式一般實現:非線程安全,getInstance返回的實例指針需要delete
class Singleton
{
public:
static Singleton* getInstance();
~Singleton(){}
private:
Singleton(){} //構造函數私有
Singleton(const Singleton& obj) = delete; //明確拒絕
Singleton& operator=(const Singleton& obj) = delete; //明確拒絕
static Singleton* m_pSingleton;
};
Singleton* Singleton::m_pSingleton = NULL;
Singleton* Singleton::getInstance()
{
if(m_pSingleton == NULL)
{
m_pSingleton = new Singleton;
}
return m_pSingleton;
}
線程安全的懶漢單例模式
std::mutex mt;
class Singleton
{
public:
static Singleton* getInstance();
private:
Singleton(){} //構造函數私有
Singleton(const Singleton&) = delete; //明確拒絕
Singleton& operator=(const Singleton&) = delete; //明確拒絕
static Singleton* m_pSingleton;
};
Singleton* Singleton::m_pSingleton = NULL;
Singleton* Singleton::getInstance()
{
if(m_pSingleton == NULL)
{
mt.lock();
if(m_pSingleton == NULL)
{
m_pSingleton = new Singleton();
}
mt.unlock();
}
return m_pSingleton;
}
返回一個reference指向local static對象
這種單例模式實現方式多線程可能存在不確定性:任何一種non-const static對象,不論它是local或non-local,在多線程環境下“等待某事發生”都會有麻煩。解決的方法:在程序的單線程啓動階段手工調用所有reference-returning函數。這種實現方式的好處是不需要去delete它。
class Singleton
{
public:
static Singleton& getInstance();
private:
Singleton(){}
Singleton(const Singleton&) = delete; //明確拒絕
Singleton& operator=(const Singleton&) = delete; //明確拒絕
};
Singleton& Singleton::getInstance()
{
static Singleton singleton;
return singleton;
}
餓漢單例模式
餓漢:餓了肯定要飢不擇食。所以在單例類定義的時候就進行實例化。在訪問量比較大,或者可能訪問的線程比較多時,採用餓漢實現,可以實現更好的性能。這是以空間換時間。
//餓漢式:線程安全,注意一定要在合適的地方去delete它
class Singleton
{
public:
static Singleton* getInstance();
private:
Singleton(){} //構造函數私有
Singleton(const Singleton&) = delete; //明確拒絕
Singleton& operator=(const Singleton&) = delete; //明確拒絕
static Singleton* m_pSingleton;
};
Singleton* Singleton::m_pSingleton = new Singleton();
Singleton* Singleton::getInstance()
{
return m_pSingleton;
}