單例模式簡(jiǎn)介

什么是設(shè)計(jì)模式

德清網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來(lái)到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。

設(shè)計(jì)模式代表了最佳實(shí)踐,是軟件開發(fā)過(guò)程中面臨一般問(wèn)題的解決方案。

設(shè)計(jì)模式是一套被反復(fù)使用、經(jīng)過(guò)分類、代碼設(shè)計(jì)總結(jié)的經(jīng)驗(yàn)。

單例模式

單例模式也叫單件模式。Singleton是一個(gè)非常常用的設(shè)計(jì)模式,幾乎所有稍微大一些的程序都會(huì)使用到它,所以構(gòu)建一個(gè)線程安全并且高效的Singleton很重要。

1. 單例類保證全局只有一個(gè)唯一實(shí)例對(duì)象。

2. 單例類提供獲取這個(gè)唯一實(shí)例的接口。

怎樣設(shè)計(jì)一個(gè)單例模式

實(shí)現(xiàn)一(不考慮線程安全)

class Singleton
{
public:
// 獲取唯一對(duì)象實(shí)例的接口函數(shù)
	static Singleton* GetInstance()
	{
		if(_sInstance == NUL)
		{
			if (_sInstance == NULL)
			{
				_sInstance = new Singleton();
			}
		}
		return _sInstance;
	}
// 刪除實(shí)例對(duì)象
	static void DelInstance()
	{
		if (_sInstance)
		{
			delete _sInstance;
			_sInstance = NULL;
		}
	}
	void Print()
	{
		cout<<_data<<endl;
	}
private:
	// 構(gòu)造函數(shù)定義為私有,限制只能在類內(nèi)創(chuàng)建對(duì)象
	Singleton()
	:_data(0)
	{}
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
	// 指向?qū)嵗闹羔樁x為靜態(tài)私有,這樣定義靜態(tài)成員函數(shù)獲取對(duì)象實(shí)例
	static Singleton* _sInstance;
	// 單例類里面的數(shù)據(jù)
	int _data;
};
Singleton* Singleton::_sInstance = NULL;

void TestSingleton()
{
	Singleton::GetInstance()->Print();
	Singleton::DelInstance();
}

實(shí)現(xiàn)二

線程安全的單例 -- (懶漢模式-- lazy loading)

ps: 下面部分的加鎖使用了C++11庫(kù)的互斥鎖
class Singleton
{
public:
	// 獲取唯一對(duì)象實(shí)例的接口函數(shù)
	static Singleton* GetInstance()
	{
	// 使用雙重檢查,提高效率,避免高并發(fā)場(chǎng)景下每次獲取實(shí)例對(duì)象都進(jìn)行加鎖
		if (_sInstance == NULL)
		{
			std::lock_guard<std::mutex> lck(_mtx);
			if (_sInstance == NULL)
			{
				// tmp = new Singleton()分為以下三個(gè)部分
				// 1.分配空間 2.調(diào)用構(gòu)造函數(shù) 3.賦值
				// 編譯器編譯優(yōu)化可能會(huì)把2和3進(jìn)行指令重排,這樣可能會(huì)導(dǎo)致
				// 高并發(fā)場(chǎng)景下,其他線程獲取到未調(diào)用構(gòu)造函數(shù)初始化的對(duì)象
				// 以下加入內(nèi)存柵欄進(jìn)行處理,防止編譯器重排柵欄后面的賦值
				// 到內(nèi)存柵欄之前
				Singleton* tmp = new Singleton();
				MemoryBarrier();
				_sInstance = tmp;
			}
		}
		return _sInstance;
	}
	// 刪除實(shí)例對(duì)象
	static void DelInstance()
	{
		std::lock_guard<std::mutex> lck(_mtx);
		if (_sInstance)
		{
			delete _sInstance;
			_sInstance = NULL;
		}
	}
	void Print()
	{
	cout<<_data<<endl;
	}
private:
	// 構(gòu)造函數(shù)定義為私有,限制只能在類內(nèi)創(chuàng)建對(duì)象
	Singleton()
	:_data(0)
	{}
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
	// 指向?qū)嵗闹羔樁x為靜態(tài)私有,這樣定義靜態(tài)成員函數(shù)獲取對(duì)象實(shí)例
	static Singleton* _sInstance;
	// 保證線程安全的互斥鎖
	static mutex _mtx;
	// 單例類里面的數(shù)據(jù)
	int _data;
};
Singleton* Singleton::_sInstance = NULL;
mutex Singleton::_mtx;

void TestSingleton()
{
Singleton::GetInstance()->Print();
Singleton::DelInstance();
}

實(shí)現(xiàn)三

線程安全的單例 --(餓漢模式--簡(jiǎn)潔、高效、不用加鎖、但是在某些場(chǎng)景下會(huì)有缺陷)

方法1

// 方式一
class Singleton
{
public:
	// 獲取唯一對(duì)象實(shí)例的接口函數(shù)
	static Singleton* GetInstance()
	{
		static Singleton sInstance;
		return &sInstance;
	}
	void Print()
	{
		cout<<_data<<endl;
	}
private:
	// 構(gòu)造函數(shù)定義為私有,限制只能在類內(nèi)創(chuàng)建對(duì)象
	Singleton()
	:_data(0)
	{}
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
	// 單例類里面的數(shù)據(jù)
	int _data;
};

void TestSingleton()
{
	Singleton::GetInstance()->Print();
}

方法2

// 方式二
class Singleton
{
public:
	// 獲取唯一對(duì)象實(shí)例的接口函數(shù)
	static Singleton* GetInstance()
	{
		assert(_sInstance);
		return _sInstance;
	}
	// 刪除實(shí)例對(duì)象
	static void DelInstance()
	{
		if (_sInstance)
		{
			delete _sInstance;
			_sInstance = NULL;
		}
	}
	void Print()
	{
		cout << _data << endl;
	}
private:
	// 構(gòu)造函數(shù)定義為私有,限制只能在類內(nèi)創(chuàng)建對(duì)象
	Singleton()
	:_data(0)
	{}
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
	// 指向?qū)嵗闹羔樁x為靜態(tài)私有,這樣定義靜態(tài)成員函數(shù)獲取對(duì)象實(shí)例
	static Singleton* _sInstance;
	// 單例類里面的數(shù)據(jù)
	int _data;
};
Singleton* Singleton::_sInstance = new Singleton;

void TestSingleton()
{
	Singleton::GetInstance()->Print();
	Singleton::DelInstance();
}

帶RAII GC 自動(dòng)回收實(shí)例對(duì)象的方式

class Singleton
{
public:
	// 獲取唯一對(duì)象實(shí)例的接口函數(shù)
	static Singleton* GetInstance()
	{
		assert(_sInstance);
		return _sInstance;
	}
	// 刪除實(shí)例對(duì)象
	static void DelInstance()
	{
		if (_sInstance)
		{
			delete _sInstance;
			_sInstance = NULL;
		}
	}
	void Print()
	{
		cout << _data << endl;
	}
	class GC
	{
		public:
		~GC()
		{
			cout << "DelInstance()"<<endl;
			DelInstance();
		}
	};
private:
	// 構(gòu)造函數(shù)定義為私有,限制只能在類內(nèi)創(chuàng)建對(duì)象
	Singleton()
	:_data(0)
	{}
	// 指向?qū)嵗闹羔樁x為靜態(tài)私有,這樣定義靜態(tài)成員函數(shù)獲取對(duì)象實(shí)例
	static Singleton* _sInstance;
	// 單例類里面的數(shù)據(jù)
	int _data;
};
// 靜態(tài)對(duì)象在main函數(shù)之前初始化,這時(shí)只有主線程運(yùn)行,所以是線程安全的。
Singleton* Singleton::_sInstance = new Singleton;
// 使用RAII,定義全局的GC對(duì)象釋放對(duì)象實(shí)例
Singleton::GC gc;
void TestSingleton()
{
	Singleton::GetInstance()->Print();
}

由于程序在結(jié)束的時(shí)候,系統(tǒng)會(huì)自動(dòng)析構(gòu)所有的全局變量,實(shí)際上,系統(tǒng)也會(huì)析構(gòu)所有類的靜態(tài)成員變量,就像這些靜態(tài)變量是全局變量一樣。我們知道,靜態(tài)變量和全局變量在內(nèi)存中,都是存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū)的,所以在析構(gòu)時(shí),是同等對(duì)待的。

分享名稱:單例模式簡(jiǎn)介
網(wǎng)址分享:http://muchs.cn/article4/ihipie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)網(wǎng)站策劃、企業(yè)網(wǎng)站制作、Google、App設(shè)計(jì)、全網(wǎng)營(yíng)銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)