c++ 中的單例類模板的實現方法

 一、什麼是單例模式

  在架構設計時,某些類在整個系統生命週期中最多隻能有一個對象存在 ( Single Instance )。如超市收銀系統,其外觀主要由顯示器(1個)、掃描槍(1個)、收款箱(1個)組成,在系統正常運行期間這三部分都是惟一存在的;也就是說,顯示器、掃描槍、收款箱這三部分都應該有各自的類,而且每一個類只能惟一地實例化一個對象,基於這種模式的程序設計,稱爲單例模式。ios

  !!!單例模式只能建立一個對象,且該對象的生命週期伴隨系統的整個運行期間。架構

二、怎麼實現單例模式

  思考:如何定義一個類,使得這個類最多隻能建立一個對象?ide

  分析:由於對象是由構造函數建立的,因此咱們應該將問題鎖定在構造函數上;又由於只能建立一個對象,這就意味着只能調用一次構造函數;顯然將構造函數的訪問權限設置爲 public 不合適,因此,構造函數的訪問權限只能是 private。而後,定義一個私有的靜態成員 c_instance = NULL 和 公有的靜態成員函數,經過  c_instance 來判斷是否建立對象。(這個爲何要使用 靜態成員呢?由於構造函數是私有的,在類的外部沒法建立對象,只能經過類名調用靜態成員,而靜態成員函數只能調用靜態成員變量) 函數

  上述分析過程可簡化爲:測試

  (1)將構造函數的訪問屬性設置爲 private;this

  (2)定義私有的靜態成員屬性 instance 並初始化爲 NULL;spa

  (3)當須要使用對象時,訪問 instance 的值;架構設計

           1)空值:建立對象,並用 instance 標記;設計

           2)非空值:返回 instance 標記的對象;指針

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class SObject
 7 {
 8     static SObject* c_instance;  // 定義標識符指針;
 9 
10     /* 不需用拷貝和賦值,在單例模式中,始終只有一個對象 */    
11     SObject(const SObject&);
12     SObject& operator= (const SObject&);
13     
14     SObject()  // 私有的構造函數
15     {
16     }
17 public:
18     static SObject* GetInstance();    // 建立對象的入口
19     
20     void print()
21     {
22         cout << "this = " << this << endl;
23     }
24 };
25 
26 SObject* SObject::c_instance = NULL; // 靜態成員類內聲明,類外定義
27 
28 SObject* SObject::GetInstance() // 單例模式的關鍵
29 {
30     if( c_instance == NULL )
31     {
32         c_instance = new SObject();
33     }
34     
35     return c_instance;
36 }
37 
38 int main()
39 {
40     SObject* s = SObject::GetInstance();
41     SObject* s1 = SObject::GetInstance();
42     SObject* s2 = SObject::GetInstance();
43     
44     s->print();    // this = 0x940a008
45     s1->print();  // this = 0x940a008
46     s2->print();  // this = 0x940a008
47     
48     return 0;
49 }
50 // 注:單例模式中,對象的生命週期存在整個系統運行過程當中,因此是絕對不釋放的;
單例模式實現

 ·   其實,在上述的單例模式實現案列中,有一部分代碼(分析過程當中第二、3步)與類自己沒有任何關係,既然是這樣,咱們就把這部分單獨提取出來處理。

  問題所在:須要使用單例模式時,必須在每一個類中定義 靜態成員變量 c_instance 和 靜態成員函數 GetInstance();當有多個類都須要使用單例模式時,這樣的實現方式明顯的很冗餘,爲了可以代碼複用,咱們能夠 將這兩部分抽象成一個新類(作成類模板,聲明爲其它類的友元類,這樣與以前的效果同樣)。

 1 // 對上個單例模式實現代碼的改進
 2 
 3 // singleton.hpp 單例模式代碼
 4 #ifndef SINGLETON_H
 5 #define SINGLETON_H
 6 
 7 template
 8 < typename T >
 9 class Singleton
10 {
11     static T* c_instance;
12 public:
13     static T* GetInstance();
14 };
15 
16 template
17 < typename T >
18 T* Singleton<T>::c_instance = NULL;
19 
20 template
21 < typename T >
22 T* Singleton<T>::GetInstance()
23 {
24     if( c_instance == NULL )
25     {
26         c_instance = new T();
27     }
28     
29     return c_instance;
30 }
31 
32 #endif
33 
34 // main.cpp 測試文件
35 #include <iostream>
36 #include <string>
37 #include "singleton.hpp"
38 
39 using namespace std;
40 
41 class SObject
42 {
43     friend class Singleton<SObject>;    // 當前類須要使用單例模式
44     
45     SObject(const SObject&);
46     SObject& operator= (const SObject&);
47     
48     SObject()
49     {
50     }
51 public:
52     
53     void print()
54     {
55         cout << "this = " << this << endl;
56     }
57 };
58 
59 int main()
60 {
61     SObject* s = Singleton<SObject>::GetInstance();
62     SObject* s1 = Singleton<SObject>::GetInstance();
63     SObject* s2 = Singleton<SObject>::GetInstance();
64     
65     s->print();    // 0xe63c20
66     s1->print();  // 0xe63c20
67     s2->print();  // 0xe63c20
68     
69     return 0;
70 }
基於類模板的單例模式實現

  在從此工做中,若是一個類(SObject)要使用單例模式(Singleton 單例模式的類模板),只需三步驟:

  (1)類(SObject)的構造函數必須私有化;同時,拷貝構造函數、重載=操做符 也私有化;

  (2)將單例模式的類模板聲明爲這個類的友元類; friend class Singleton<SObject>; 

  (3)經過 單例模式類模板中 SObject* s = Singleton<SObject>::GetInstance(); 建立對象。

相關文章
相關標籤/搜索