單例模式也稱單子模式、單件模式,經過單例模式能夠保證系統中只有一個類只有一個實例,並提供一個訪問它的全局訪問點,該實例被全部程序模塊共享數據庫
對於系統中的某些類來講,只有一個實例很重要,好比一個打印機能夠有多個打印任務,可是隻有一個正在工做的任務,一個系統只能有一個窗口管理器或文件系統 安全
單例模式的要點有三個;1. 單例類只能有一個實例 2. 它必須自行建立這個實例 3. 它必須自行向整個系統提供提供這個實例函數
從具體實現角度來講,就是如下三點: 1. 單例模式的類只提供私有的構造函數 2. 類定義中含有一個該類的靜態私有對象 3. 該類提供了一個靜態的公有的函數用於建立或獲取它自己的靜態私有對象工具
單例模式的一些注意點性能
一 實例控制: 單例模式會阻止其餘對象實例化本身的單例對象的副本,從而確保全部對象都訪問惟一實例spa
二 靈活性: 由於類控制實例化過程,因此類能夠靈活更改實例化過程線程
三 開銷: 雖然數量不多,但若是每次對象請求引用時都要檢查是否存在類的實例,將仍然須要一些開銷,這個問題能夠經過靜態初始化解決此問題指針
定義一個私有的靜態指針m_sInstance,和一個公有的靜態函數 GetInstance(),code
單例模式又分爲餓漢式單例和懶漢式單例,餓漢式單例在單例類被加載時就實例化一個對象交給本身的引用;而懶漢式在調用取得實例方法的時候纔會實例化對象對象
單例模式的優勢:
1. 在內存中只有一個對象,節省內存空間
2. 避免頻繁的建立銷燬對象,能夠提升性能
3. 避免對共享資源的多重佔用
4. 能夠全局訪問
單例模式的適用場景:
1. 須要頻繁實例化而後銷燬的對象
2. 建立對象耗時過多或者耗資源過多,但又常常用到的對象
3. 有狀態的工具類對象
4. 頻繁訪問數據庫或文件的對象
5. 以及其餘要求只有一個對象的場景
在C++ 中通常都使用懶漢式單例,但懶漢式單例可能會有線程安全,異常安全問題
實例代碼以下:
1 class CSingleton 2 { 3 private: 4 CSingleton() //構造函數是私有的 5 { 6 } 7 public: 8 static CSingleton * GetInstance() 9 { 10 static CSingleton *m_pInstance; 11 if(m_pInstance == NULL) //判斷是否第一次調用 12 m_pInstance = new CSingleton(); 13 return m_pInstance; 14 } 15 };
對於拷貝構造和分配操做符若是咱們不打算自定義的話,那麼最好將它們也置爲私有且不實現
考慮到線程安全和異常安全,實現代碼以下:
1 class Lock 2 { 3 private: 4 CCriticalSection m_cs; 5 public: 6 Lock(CCriticalSection cs) : m_cs(cs) 7 { 8 m_cs.Lock(); 9 } 10 ~Lock() 11 { 12 m_cs.Unlock(); 13 } 14 }; 15 16 class CSingleton 17 { 18 private: 19 CSingleton(); 20 CSingleton(const CSingleton &); 21 CSingleton& operator = (const CSingleton &); 22 23 public: 24 static CSingleton *Getinstance(); 25 static CSingleton *m_Instance; 26 static CCriticalSection cs; 27 }; 28 29 CSingleton* CSingleton::m_Instance = 0; 30 31 CSingleton* CSingleton::Getinstance() 32 { 33 if(m_Instance == NULL) 34 { //double check 35 Lock lock(cs); //用lock實現線程安全,用資源管理類,實現異常安全 36 //使用資源管理類,在拋出異常的時候,資源管理類對象會被析構,析構老是發生的不管是由於異常拋出仍是語句塊結束。 37 if(m_Instance == NULL) 38 { 39 m_Instance = new Singleton(); 40 } 41 } 42 return m_Instance; 43 }
之因此在Instantialize函數裏面對pInstance 是否爲空作了兩次判斷,由於該方法調用一次就產生了對象,pInstance == NULL 大部分狀況下都爲false,若是按照原來的方法,每次獲取實例都須要加鎖,效率過低。而改進的方法只須要在第一次 調用的時候加鎖,可大大提升效率。