[C++] 單例模式:餓漢、懶漢demo


設計模式

設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、經過分類的、代碼設計經驗的總結。早期有23種設計模式。

  • 爲什麼會產生設計模式呢?

就像人類歷史發展會產生兵法。最開始部落之間打仗時都是人拼人的對砍。後來春秋戰國時期,七國之間經常打仗,就發現打仗也是有套路的,後來孫子就總結出了《孫子兵法》。孫子兵法也是類似。

  • 使用設計模式的目的?

爲了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。 設計模式使代碼編寫真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構一樣。


單例模式

一個類只能創建一個對象,即單例模式,該模式可以保證系統中該類只有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。
比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息,這種方式簡化了在複雜環境下的配置管理。

單例模式有兩種實現模式:

  1. 餓漢模式
    就是說不管你將來用不用,程序啓動前就創建一個唯一的實例對象。
    【如果這個單例對象在多線程高併發環境下頻繁使用,性能要求較高,那麼顯然使用餓漢模式來避免資源競爭,提高響應速度更好】

  2. 懶漢模式
    如果單例對象構造十分耗時或者佔用很多資源,比如加載插件啊, 初始化網絡連接啊,讀取文件啊等等,而有可能該對象程序運行時不會用到,那麼也要在程序一開始就進行初始化,就會導致程序啓動體驗非常的緩慢。 所以這種情況使用懶漢模式(延遲加載)更好。

餓漢模式

這個對象在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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章