單例模式:一個類只能創建一個對象。單例模式是C++中常用的一種設計模式,熟悉Qt的朋友肯定清楚QApplication實際也是採用的單例模式,並且爲用戶提供了一個全局的指針對象 qApp。我們先看看Qt中對於單例的實現:
#define qApp QCoreApplication::instance()
class Q_CORE_EXPORT QCoreApplication : public QObject
{
Q_OBJECT
public:
QCoreApplication(int &argc, char **argv, int _internal = ApplicationFlags);
~QCoreApplication();
static QCoreApplication *instance() { return self; } // 返回對象本身
private:
static QCoreApplication *self;
};
QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal)
: QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
{
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = this;
}
QCoreApplication::~QCoreApplication()
{
self = 0;
// ...
}
看完上面的代碼,有點啓發。現在回到我們的主題,我們如何自己實現單例模式呢。
單例模式分爲餓漢式和懶漢式兩種,
單例模式 | 優點 | 缺點 |
懶漢式 | 只有在調用相應的方法時,纔會構造對象 | 每次都要進行判斷,程序進行慢 |
餓漢式 | 不管需不需要對象空間,都先提前佈局好對象空間; | 存在內存空間的浪費 |
#include <QCoreApplication>
#include <iostream>
#include <QDebug>
using namespace std;
/**
* @brief The mySingleton class 指針對象模式
* 維護一個唯一的全局指針對象
*/
class mySingleton{
private:
mySingleton(){}
public:
static mySingleton* getInstance(){
#ifndef Hungary_Model // 餓漢模式
#else // 懶漢模式
if(m_ps1 == NULL) m_ps1 = new mySingleton;
#endif
return m_ps1;
}
static void freeInstance(){
if(m_ps1){
delete m_ps1;
m_ps1 = NULL;
}
}
private:
static mySingleton* m_ps1;
};
#ifndef Hungery_Model // 餓漢模式
mySingleton *mySingleton::m_ps1 = new mySingleton;
#else // 懶漢模式
mySingleton *mySingleton::m_ps1 = NULL;
#endif
/**
* @brief The RenfrenceSingleton class 引用模式
* 維護一個全局的單例對象
*/
class RenfrenceSingleton
{
public:
static RenfrenceSingleton rSingleton;
private:
RenfrenceSingleton() {
cout << "RenfrenceSingleton constructor" << endl;
}
public:
static RenfrenceSingleton& getInstance(){
return rSingleton;
}
};
RenfrenceSingleton RenfrenceSingleton::rSingleton;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
mySingleton* mp1 = mySingleton::getInstance();
mySingleton* mp2 = mySingleton::getInstance();
cout << "[ptr singleton] " << mp1 << " "<< mp2 << endl;
mySingleton::freeInstance();
RenfrenceSingleton& r1 = RenfrenceSingleton::getInstance();
RenfrenceSingleton& r2 = RenfrenceSingleton::getInstance();
cout << "[reference singleton] " << &r1 <<" " << &r2 << endl;
return a.exec();
}
通過打印結果可以看到,無論是使用指針對象或者引用對象的方法,實際上操作的都是同一實例。