設計模式
設計模式(Design Pattern
)是一套被反覆使用、多數人知曉的、經過分類的、代碼設計經驗的總結。早期有23
種設計模式。
- 爲什麼會產生設計模式呢?
就像人類歷史發展會產生兵法。最開始部落之間打仗時都是人拼人的對砍。後來春秋戰國時期,七國之間經常打仗,就發現打仗也是有套路的,後來孫子就總結出了《孫子兵法》。孫子兵法也是類似。
- 使用設計模式的目的?
爲了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。 設計模式使代碼編寫真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。
單例模式
一個類只能創建一個對象,即單例模式,該模式可以保證系統中該類只有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。
比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息,這種方式簡化了在複雜環境下的配置管理。
單例模式有兩種實現模式:
-
餓漢模式
就是說不管你將來用不用,程序啓動前就創建一個唯一的實例對象。
【如果這個單例對象在多線程高併發環境下頻繁使用,性能要求較高,那麼顯然使用餓漢模式來避免資源競爭,提高響應速度更好】 -
懶漢模式
如果單例對象構造十分耗時或者佔用很多資源,比如加載插件啊, 初始化網絡連接啊,讀取文件啊等等,而有可能該對象程序運行時不會用到,那麼也要在程序一開始就進行初始化,就會導致程序啓動體驗非常的緩慢。 所以這種情況使用懶漢模式(延遲加載)更好。
餓漢模式
這個對象在main
函數執行前就創建好了。
class Singleton{
public:
static Singleton* GetInstance(){
return &m_instance;
}
private:
Singleton() {}; //私有構造函數
//C++98
Singleton(Singleton const&);
Singleton& operator=(const Singleton&);
//或者C++11新特性:< 刪除函數 >
////Singleton(Singleton const&) = delete;
////Singleton& operator=(const Singleton&) = delete;
static Singleton m_instance; //靜態/全局的,它屬於整個類
};
Singleton Singleton::m_instance; //真正的定義在這裏
通過代碼查看一下對象地址:
int main() {
cout << Singleton::GetInstance() << endl;
cout << Singleton::GetInstance() << endl;
cout << Singleton::GetInstance() << endl;
system("pause");
}
輸出結果:
0113B138
0113B138
0113B138
可見使用的都是同一個單例~
懶漢模式
不再是一個實例對象,而是指向實例對象的一個指針
class Singleton {
public:
static Singleton* GetInstance() {
if (_spinst == nullptr) { //表示第一次調用,第二次不會進if邏輯,每次處理的同一個實例對象
_spinst = new Singleton;
}
return _spinst;
}
private:
Singleton() {} //私有構造函數
//防拷貝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton* _spinst;
};
Singleton* Singleton::_spinst = nullptr;
輸出結果:
0051B888
0051B888
0051B888
同樣使用的是同一個單例~
但這個懶漢模式不是線程安全的,如果多個線程同時第一次去調用GetInstance()
,兩個線程都會進入if
語句,則各個線程會實例各自的指針而出現錯誤。所以改進方法就是加互斥鎖。
線程安全版本:
class Singleton {
public:
//mutex是在靜態成員函數instance()中使用,所以要指定爲靜態屬性
static pthread_mutex_t mutex;
static Singleton* GetInstance() {
//double check:雙檢查,減少加鎖次數,提高效率
if (_s == nullptr) {
pthread_mutex_lock(&mutex);
if (_s == nullptr) {
_s = new Singleton;
}
pthread_mutex_unlock(&mutex);
}
return _s;
}
private:
static Singleton* _s;
Singleton() {
pthread_mutex_init(&mutex);
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
Singleton* Singleton::_s = nullptr;