您好,登錄后才能下訂單哦!
1、單例模式
(1)需求的提出:在架構設計時,某些類在整個系統生命周期中最多只能有一個對象存在(Single,Instance)
(2)問題:如何定義一個類,使得這個類最多只能創建一個對象?
要控制類的對象數目,必須對外隱藏構造函數
思路:
@1:將構造函數的訪問屬性設置為private,將拷貝構造函數,賦值操作符都聲明成private的,防止對象的賦值操作,因為這個類的對象只能有一個。
@2:定義instance并初始化為NULL。在類中用static type* instance的方式聲明一個靜態的變量,按照對這個static修飾的訪問規則,之后在類外面進行定義初始化為NULL。
@3:然后在類中在提供一個static的成員函數,用來創建對象的,當我們要創建對象的時候,必然會用調用這個函數,這個函數內部就會去訪問instance。 @4:訪問instance的值,空值時:創建對象,并用instance進行標記(也就是如果instance為NULL,則直接new一個對象出來將地址賦值給
instance,讓instance進行標記),然后返回這個對象。非空值時:直接返回instance標記的對象。這樣就保證了這個類只能創建一個對象,這就是單例模式。‘
單例模式的對象在整個系統的運行過程當中是絕對不需要釋放的,當系統結束運行時,系統自然就會釋放這個對象了。所以單例模式的對象不需要在系統運行的時候,也就是不需要在系統生命周期
還沒有結束時進行釋放。
例:單例模式
#include <iostream>
using namespace std;
/*
* 單例模式
* why 2016/9/6
*
* 實現單例模式的思路:
*
* @1:將構造函數的訪問屬性設置為private,將拷貝構造函數,賦值操作符都聲明成private的,防止對象的賦值操作,因為這個類的對象只能有一個。
* @2:定義instance并初始化為NULL。在類中用static type* instance的方式聲明一個靜態的變量,按照對這個static修飾的訪問規則,之后在類外面進行定義初始化為NULL。
* @3:然后在類中在提供一個static的成員函數,用來創建對象的,當我們要創建對象的時候,必然會用調用這個函數,這個函數內部就會去訪問instance。
* @4:訪問instance的值,空值時:創建對象,并用instance進行標記(也就是如果instance為NULL,則直接new一個對象出來將地址賦值給
* instance,讓instance進行標記),然后返回這個對象。非空值時:直接返回instance標記的對象。這樣就保證了這個類只能創建一個對象,這就是單例模式。‘
*/
/*
* 單例模式的對象在整個系統的運行過程當中是絕對不需要釋放的,當系統結束運行時,系統自然就會釋放這個對象了。所以單例模式的對象不需要在系統運行的時候,
* 也就是不需要在系統生命周期還沒有結束時進行釋放。
*/
class SObject
{
private:
SObject() //將構造函數隱藏起來
{
}
SObject(const SObject&); //將拷貝構造函數隱藏起來
SObject& operator = (const SObject&); //將賦值操縱隱藏起來
static SObject *c_instance; //聲明一個instance的SObject的指針,將來用來標記創建的對象的,也是指向那個對象的指針。因為是static的,所以需要在外部進行定義,初始化為NULL
public:
static SObject* GetInstance(); //聲明,用來創建一個對象的,因為你的構造函數已經為private的,所以我們要自己提供一個。因為static的,所以也要在外部進行定義
void print()
{
cout << "this = " << this << endl;
}
};
SObject* SObject::c_instance = NULL;
SObject* SObject::GetInstance()
{
if (c_instance == NULL)
{
c_instance = new SObject(); //如果c_instance這個標記為空,說明沒有對象創建,則創建唯一一個對象
}
return c_instance; //返回這個創建的對象的指針
}
int main(void)
{
SObject* s1 = SObject::GetInstance();
SObject* s2 = SObject::GetInstance();
s1->print(); //this = 0x893d008
s2->print(); //this = 0x893d008 //說明確實只能創建一個對象,因為兩個指針指向的都是一個對象
return 0;
}
2、上面的代碼實現了單例模式,但是還不是很完美,比如需要定義靜態變量c_instance,必須要定義靜態成員函數GetIntance(),所以我們可以在完美一下。
解決方案就是:將單例模式相關的代碼抽取出來,就是單例模式本身的邏輯模式那部分,不影響類的其他功能,將這部分代碼拿出來后開發出單例類模板。當需要單例類時,直接使用單例類模板。
使用方式是,在需要使用單例類模式的類中,用友元關鍵friend + class + 單例類模板的名字<當前類的名字>,將單例類模板聲明為當前類的友元。在單例類模板中實現的是定義靜態變量用來
標記對象,和定義靜態成員函數來實現判斷標記從而決定是否創建新的對象和返回對象的地址。
Singleton英文是單例模式的意思。
3、好的使用單例模式類的例子:
/************************************************單例類模板程序*****************************************/
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
/*
* 單例類模板
* 實現單例模式的邏輯那部分。以后其他的類如果想用單例模式都可以添加將這個單例類模板聲明為友元,T是使用該模板的類名,進行實現單例模式
*/
template
< typename T >
class Singleton
{
private:
static T* c_instance;
public:
static T* GetInstance();
};
template
< typename T >
T* Singleton<T>::c_instance = NULL; //將這個標記首先置位空
template
< typename T >
T* Singleton<T>::GetInstance()
{
if (c_instance == NULL) //看是否使用單例模式的類已經定義過對象了。
{
c_instance = new T(); //沒有定義對象,則創建一個對象//沒有定義對象,則創建一個對象
}
return c_instance; //最后返回這個對象的指針,這個標記就記錄著這個對象的地址。這樣防止對象對此定義。
}
#endif
/*************************************************使用這個單例類模板而實現的單例模式的類*******************************/
#include <iostream>
#include "Singleton.h"
using namespace std;
/*
* SObject使用單例模式,方式是使用的添加單例類模板進行實現的
*
*
*/
//同時必須要將一些跟對象的創建有關的函數弄成private的,隱藏起來。包括:構造函數、拷貝構造函數、賦值操作符重載函數
class SObject
{
private:
friend class Singleton<SObject>; //將使用的單例類模板聲明為當前這個類的友元。這樣即可達到使用單例類模板。
SObject()
{
}
SObject(const SObject&);
SObject& operator = (const SObject&);
public:
void print()
{
cout << "this = " << this << endl;
}
};
int main(void)
{
SObject *s1 = Singleton<SObject>::GetInstance();
SObject *s2 = Singleton<SObject>::GetInstance();
SObject *s3 = Singleton<SObject>::GetInstance();
s1->print(); //會發現三個的指針值都是一樣,說明都是指向的同一個對象,說明單例模式實現成功,單例模式下的類只能創建一個對象
s2->print();
s3->print();
return 0;
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。