單例模式的c++實現 ...
1 #pragma once 2 3 #include <iostream> 4 #include <memory> 5 #include <Windows.h> 6 using namespace std; 7 /*************************************************************************************** 8 9 1、首先要有一個創建實例的靜態函數GetInstance 10 2、實現的方式既可以通過new動態創建,也可以通過static靜態局部變數實現 11 3、創建的時機既可以通過靜態變數初始化時創建,也可以在調用GetInstance函數時再創建,通過靜態變數的初始化的好處是 12 它是在進入主函數之前創建成功的可以避免多線程的問題,但是壞處就是在程式啟動時初始化會拖慢啟動過程。 13 4、為了防止通過調用構造函數創建實例,要將類的構造、複製構造和賦值構造函數設為私有的 14 5、GetInstance函數的返回值既可以是指針,又可以是引用,當是指針的時候要防止它在中途被delete掉,因此要將析構函數設為私有的 15 6、這種模式有點像全局變數,但還是有區別的,單件的作用是保證只有一份實例,而能夠全局訪問是它附帶的功能。 16 17 ********************************************************////////////////////////////////////// 18 class singleton1 19 { 20 public: 21 static singleton1* GetInstance() 22 { 23 if(ptr == NULL) 24 ptr = new singleton1; 25 return ptr; 26 } 27 28 static void show() 29 { 30 cout << "singleton1::show" << endl; 31 } 32 33 private: 34 ~singleton1() 35 { 36 cout << "dest singleton1" << endl; 37 } 38 static singleton1* ptr; 39 singleton1() 40 { 41 cout << "cstr singleton1" << endl; 42 } 43 44 singleton1(const singleton1 &); 45 singleton1& operator=(const singleton1 &); 46 }; 47 48 singleton1* singleton1::ptr = new singleton1; 49 50 /***************** 51 1、在上面的實現中,使用指針時,不能銷毀實例,只有當程式結束時才由系統回收,考慮將指針設計成智能指針shared_ptr, 52 但是智能指針的回收還是要調用析構函數,聲明為public,指針隨時會被delete,有很多問題,所以這種方法是不太實用 53 *****************/ 54 class singleton3 55 { 56 public: 57 ~singleton3() 58 { 59 cout << "dest singleton3" << endl; 60 } 61 62 static singleton3* GetInstance() 63 { 64 if(ptr.get() == NULL) 65 ptr.reset(new singleton3); 66 return ptr.get(); 67 } 68 69 static void show() 70 { 71 cout << "singleton3::show" << endl; 72 } 73 74 private: 75 static shared_ptr<singleton3> ptr; 76 singleton3(){} 77 singleton3(const singleton3 &); 78 singleton3& operator=(const singleton3 &); 79 }; 80 81 shared_ptr<singleton3> singleton3::ptr; 82 83 /**************************************** 84 1、上面的實現都是基於new動態創建,並且返回的都是指針類型,這個實現基於靜態局部變數,並且返回引用類型 85 2、返回引用而不是指針的好處是,不用擔心中間會被delete掉 86 3、採用靜態局部變數的好處是,記憶體管理交給系統,不需要手動管理 87 ****************************************/ 88 class singleton4 89 { 90 public: 91 ~singleton4() 92 { 93 cout << "dest singleton4" << endl; 94 } 95 96 static singleton4& GetInstance() 97 { 98 static singleton4 s; 99 return s; 100 } 101 102 static void show() 103 { 104 cout << "singleton4::show" << endl; 105 } 106 107 private: 108 singleton4(){;} 109 singleton4(const singleton4 &); 110 singleton4& operator=(const singleton4 &); 111 }; 112 113 /*************************** 114 1、如果是在GetInstance函數中創建實例,並且是多線程的話,如果有多個線程同時調用該函數, 115 則可能會創建多個實例,所以要對創建過程進行加鎖處理 116 **************************/ 117 CRITICAL_SECTION g_cs; 118 class Lock 119 { 120 public: 121 Lock() 122 { 123 InitializeCriticalSection(&g_cs); 124 } 125 126 void LockOn() 127 { 128 EnterCriticalSection(&g_cs); 129 } 130 131 void LockOff() 132 { 133 LeaveCriticalSection(&g_cs); 134 } 135 136 ~Lock() 137 { 138 DeleteCriticalSection(&g_cs); 139 } 140 }; 141 Lock g_lock; 142 143 class singleton5 144 { 145 public: 146 ~singleton5() 147 { 148 cout << "dest singleton5" << endl; 149 } 150 151 static singleton5* GetInstance() 152 { 153 if(ptr == NULL) 154 { 155 //採用雙重判斷是為了提高效率,防止每次都要執行加鎖過程 156 g_lock.LockOn(); 157 if(ptr == NULL) 158 ptr = new singleton5; 159 g_lock.LockOff(); 160 } 161 162 return ptr; 163 } 164 165 static void show() 166 { 167 cout << "singleton5::show" << endl; 168 } 169 170 private: 171 static singleton5* ptr; 172 singleton5(){} 173 singleton5(const singleton5 &); 174 singleton5& operator=(const singleton5 &); 175 }; 176 singleton5* singleton5::ptr = NULL; 177 178 /****************** 179 1、上面的實現雖然滿足了多線程調用,但是實際中可能會有很多類都要設計成實例模式, 180 那麼就需要都按照上面那樣實現一遍,不能重用,下麵的模板類就可以滿足重用的需求 181 *******************************/ 182 template <typename T> 183 class Singleton 184 { 185 public: 186 static T& Instance() 187 { 188 if (m_pInstance == NULL) 189 { 190 //Lock lock; 191 g_lock.LockOn(); 192 if (m_pInstance == NULL) 193 { 194 m_pInstance = new T; 195 atexit(&Destroy);//將Destroy註冊為程式結束時的執行函數釋放記憶體 196 } 197 198 //return *m_pInstance; 199 g_lock.LockOff(); 200 } 201 202 return *m_pInstance; 203 } 204 205 protected: 206 Singleton(void) 207 { 208 cout << "cstr Singleton" << endl; 209 } 210 virtual ~Singleton(void) 211 { 212 cout << "dest Singleton" << endl; 213 } 214 215 private: 216 Singleton(const Singleton& rhs) 217 { 218 cout << "copy cstr Singleton" << endl; 219 } 220 Singleton& operator = (const Singleton& rhs) 221 { 222 cout << "= cstr Singleton" << endl; 223 } 224 225 static void Destroy() 226 { 227 if (m_pInstance != NULL) 228 delete m_pInstance; 229 m_pInstance = NULL; 230 } 231 232 static T* m_pInstance; 233 }; 234 235 template <typename T> 236 T* Singleton<T>::m_pInstance = NULL; 237 238 //實際的單例類就按照下麵的方式實現 239 class SingletonInstance : public Singleton<SingletonInstance> 240 { 241 public: 242 friend Singleton<SingletonInstance>; 243 void show() 244 { 245 cout << "SingletonInstance::show" << endl; 246 } 247 // 248 private: 249 SingletonInstance() 250 { 251 cout << "cstr SingletonInstance" << endl; 252 } 253 virtual ~SingletonInstance(void) 254 { 255 cout << "dest SingletonInstance" << endl; 256 } 257 258 SingletonInstance(const SingletonInstance& rhs) 259 { 260 cout << "copy cstr SingletonInstance" << endl; 261 } 262 }; 263 264 //測試類 265 class SingletonTest 266 { 267 public: 268 SingletonTest() 269 { 270 //singleton1& s1 = singleton1::GetInstance1(); 271 //s1.show(); 272 273 //singleton1 *p1 = singleton1::GetInstance(); 274 //p1->show(); 275 ////delete p1; 276 277 //singleton3 *p3 = singleton3::GetInstance(); 278 //p3->show(); 279 280 //singleton4 &p4 = singleton4::GetInstance(); 281 //p4.show(); 282 283 //singleton5 *p5 = singleton5::GetInstance(); 284 //p5->show(); 285 286 SingletonInstance &si = SingletonInstance::Instance(); 287 si.show(); 288 } 289 };