单例模式:一个类只能创建一个对象。单例模式是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();
}
通过打印结果可以看到,无论是使用指针对象或者引用对象的方法,实际上操作的都是同一实例。