1. 程式人生 > 其它 >Qt 單例模式的實現(4種方法)

Qt 單例模式的實現(4種方法)

最簡單的寫法:

1 static MyClass* MyClass::Instance()
2 {
3     static MyClass inst;
4     return &inst;
5 }

過去很長一段時間一直都這麼寫,簡單粗暴有效。但是直接宣告靜態物件會使編譯出的可執行檔案增大,也有可能出現其他的一些問題,所以利用了Qt自帶的智慧指標QScopedPointer和執行緒鎖QMutex,改成了需要時才動態初始化的模式:

 1 static MyClass* MyClass::Instance()
 2 {
 3     static QMutex mutex;
 4     static
QScopedPointer<MyClass> inst; 5 if (Q_UNLIKELY(!inst)) { 6 mutex.lock(); 7 if (!inst) { 8 inst.reset(new MyClass); 9 } 10 mutex.unlock(); 11 } 12 return inst.data(); 13 }

既保證了執行緒安全又防止了記憶體洩漏,效率也沒降低太多,簡直完美。

可惜每次都要重複這麼幾行實在麻煩,於是寫了一個模板類:

 1 template <class T>
 2 class Singleton
 3 {
 4 public:
 5     static T* Instance()
 6     {
 7         static QMutex mutex;
 8         static QScopedPointer<T> inst;
 9         if (Q_UNLIKELY(!inst)) {
10             mutex.lock();
11             if (!inst) {
12                 inst.reset(new
T); 13 } 14 mutex.unlock(); 15 } 16 return inst.data(); 17 } 18 };

使用的時候直接這樣——

MyClass* inst = Singleton<MyClass>::Instance();

除了用模板類,還可以利用c++中強大的巨集:

 1 #define DECLARE_SINGLETON(Class) \
 2 Q_DISABLE_COPY(Class) \
 3 public: \
 4     static Class* Instance() \
 5     { \
 6         static QMutex mutex; \
 7         static QScopedPointer<Class> inst; \
 8         if (Q_UNLIKELY(!inst)) { \
 9             mutex.lock(); \
10             if (!inst) inst.reset(new Class); \
11             mutex.unlock(); \
12         } \
13         return inst.data(); \
14     }

然後宣告的時候,填加一行這個巨集:

1 class MyClass
2 {
3     DECLARE_SINGLETON(MyClass);    // 宣告單例模式
4     //...
5 }

好評好評。

當然,為了要保證真的是單例模式,還要把建構函式限制為private,不然以後什麼時候忘記了這碼事,在外面又new了一下就不好了。

另外Qt本身自帶了一個巨集Q_GLOBAL_STATIC,也有類似單例模式的效果,QThreadPool::globalInstance()函式的實現就是利用了這個巨集。不過它的主要用處是宣告全域性變數,和Singleton還是有差別的。