最近比較比較悠閒,複習了下設計模式中的單例模式,對於單例模式,網上有不少實例,可是看來看去,不少感受總是差點什麼,固然也有比較多的寫的很好,因此決定本身動手練習下,順便記錄下,就當記筆記了。html
在實際的開發中,幾乎每一個項目都使用到單例模式,由於不少時候,一個類只能建立一個對象,即存在惟一實例,單例就是最恰當的解決辦法了。下面就分爲在單線程中和多線程的來記錄吧!設計模式
在單線程中,網上有不少懶漢模式,餓漢模式什麼的,這些能夠本身去百度,就說下我本身比較經常使用的一種,直接上代碼比較直觀:安全
class CSingletonTwo { private: CSingletonTwo(){}//構造函數私有 public: static CSingletonTwo& getInstance(void); void init(void) { qDebug()<<" Test CSingletonTwo.........."; } }; CSingletonTwo& CSingletonTwo::getInstance() { static CSingletonTwo instance; return instance; }
這種方法(前提單線程中使用這個單例)我感受是比較簡單明瞭的一種,網上還有一些用下面方法實現,但感受仍是不如上面的簡單明瞭(固然,各有的想法,蘿蔔青菜,各有所愛。),如:多線程
class singleton { protected: singleton(){} private: static singleton* p; public: static singleton* instance(); }; singleton* singleton::p = NULL; singleton* singleton::instance() { if (p == NULL) p = new singleton(); return p; }
多線程安全模式,用到了Qt的原子指針和C++模板,具體以下:函數
#include <QCoreApplication> #include <QAtomicPointer> #include <QReadWriteLock> #include <QMutex> #include <qDebug> template<class T> class CSingleton { private: CSingleton();//防止構造函數 CSingleton(const CSingleton<T> &);//防止拷貝構造函數 CSingleton<T>& operator=(const CSingleton<T>&);//防止賦值拷貝構造函數 QReadWriteLock m_internalMutex;//讀寫鎖 static QMutex m_mutex;//互斥鎖 static QAtomicPointer<T> m_instance;//實例 public: static T& getInstance(void);//獲取惟一實例 }; template<class T> QMutex CSingleton<T>::m_mutex(QMutex::Recursive);//一個線程能夠屢次鎖同一個互斥量 template<class T> QAtomicPointer<T>CSingleton<T>::m_instance;//原子指針,默認初始化是0 template<typename T> T& CSingleton<T>::getInstance(void) { #ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE if(!QAtomicPointer<T>::isTestAndSetNative())//運行時檢測 #endif { QMutexLocker locker(&m_mutex);//互斥鎖 if(m_instance.testAndSetOrdered(0, 0))//第一次檢測 { m_instance.testAndSetOrdered(0, new T);//第二次檢測 } return *m_instance.load(); } } class CTest { public: CTest(){} void init(void) { qDebug()<<" Test singteon!!!!!!!!!!"; } }; typedef CSingleton<CTest> test;//這裏使用CTest來實例化這個模板,還能夠本身定義其餘類了來實例化,省去在每一個使用單例的類中都實現一個單例的麻煩了
上面的多線程模式及其原子操做,參考了:https://www.cnblogs.com/codingmylife/archive/2010/07/14/1777409.html,可是在這基礎上加入了模板來實現,使用多種類型。我看網上也有使用繼承來達到單例適用多個類型,那樣也沒有很差,只是代碼比較繁瑣,倒不如使用模板來的爽快。測試
下面是測試代碼:spa
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); test::getInstance().init(); CSingletonTwo::getInstance().init(); return a.exec(); }
下面是在Qt5.3.2上測試的輸出:線程