今天我也来讲讲单例模式的实现,单例模式有很多种实现方式,像饿汉,懒汉,饿汉变种,懒汉变种等等。我这边就只介绍两种方式,一种动态创建,一种静态创建。
动态创建,很多人也把它叫做懒汉式的变种在变种,因为它是一种线程安全的,并且用时才创建的,相比静态创建它启动快些。
.h
#ifndef LAZYSINGLETON_H
#define LAZYSINGLETON_H
#include <QMutex>
class LazySingleton
{
public:
static LazySingleton* getinstance();
void testfunc();
void setval(int index);
private:
LazySingleton();
static QMutex m_mutex;
static LazySingleton* m_pInstance;
int m_index;
};
#endif // LAZYSINGLETON_H
.cpp
#include "lazysingleton.h"
#include <QDebug>
QMutex LazySingleton::m_mutex;
LazySingleton* LazySingleton::m_pInstance = NULL;
LazySingleton::LazySingleton()
{
m_index = 0;
}
LazySingleton *LazySingleton::getinstance()
{
//如果只是锁定+一次检查,则每次调用都要加锁,大大降低了性能;
//如果只是一次检查+锁定,则会出现并发条件。
if (m_pInstance == NULL)
{
m_mutex.lock();
if (m_pInstance == NULL)
m_pInstance = new LazySingleton();
m_mutex.unlock();
}
return m_pInstance;
}
void LazySingleton::testfunc()
{
qWarning()<<"动态单例测试,也可以认为是线程安全的懒汉式";
}
void LazySingleton::setval(int index)
{
m_index=m_index+index;
qWarning()<<"动态单例测试,也可以认为是线程安全的懒汉式:"<<m_index;
}
静态创建,很多人也把它叫做饿汉式的变种,我认为它也是一种线程安全的,很多人说多线程情况下,它也会出现并发创建静态实例对象,但是我不这么认为,当然我可能没理解,有知道的麻烦解答一下。
.h
#ifndef HUNGRYSINGLETON_H
#define HUNGRYSINGLETON_H
class HungrySingleton
{
public:
static HungrySingleton* getinstance();
void testfunc();
void setval(int index);
private:
HungrySingleton();
int m_index;
};
#endif // HUNGRYSINGLETON_H
#include "hungrysingleton.h"
#include <QDebug>
HungrySingleton::HungrySingleton()
{
m_index = 0;
}
HungrySingleton *HungrySingleton::getinstance()
{
static HungrySingleton m_pInstance;
return &m_pInstance;
}
void HungrySingleton::testfunc()
{
qWarning()<<"静态单例测试,也可以认为是线程安全的饿汉式";
}
void HungrySingleton::setval(int index)
{
m_index = m_index+index;
qWarning()<<"静态单例测试,也可以认为是线程安全的饿汉式:"<<m_index;
}
测试:
.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtWidgets>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void slottestLazySingleton();
void slottestHungrySingleton();
void slottestLazySingletonval1();
void slottestLazySingletonval2();
void slottestHungrySingletonval1();
void slottestHungrySingletonval2();
private:
QPushButton* m_lazybtn;
QPushButton* m_lazysetvalbtn1;
QPushButton* m_lazysetvalbtn2;
QPushButton* m_hungrybtn;
QPushButton* m_hungrysetvalbtn1;
QPushButton* m_hungrysetvalbtn2;
};
#endif // WIDGET_H
.cpp
#include "widget.h"
#include "lazysingleton.h"
#include "hungrysingleton.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
m_lazybtn = new QPushButton("动态单例",this);
m_lazysetvalbtn1 = new QPushButton("1-动态单例值加1",this);
m_lazysetvalbtn2 = new QPushButton("2-动态单例值加1",this);
m_hungrybtn = new QPushButton("静态单例",this);
m_hungrysetvalbtn1 = new QPushButton("1-静态单例值加1",this);
m_hungrysetvalbtn2 = new QPushButton("2-静态单例值加1",this);
QVBoxLayout* lay = new QVBoxLayout;
lay->addWidget(m_lazybtn);
lay->addWidget(m_lazysetvalbtn1);
lay->addWidget(m_lazysetvalbtn2);
lay->addWidget(m_hungrybtn);
lay->addWidget(m_hungrysetvalbtn1);
lay->addWidget(m_hungrysetvalbtn2);
this->setLayout(lay);
connect(m_lazybtn,SIGNAL(clicked()),this,SLOT(slottestLazySingleton()));
connect(m_lazysetvalbtn1,SIGNAL(clicked()),this,SLOT(slottestLazySingletonval1()));
connect(m_lazysetvalbtn2,SIGNAL(clicked()),this,SLOT(slottestLazySingletonval2()));
connect(m_hungrybtn,SIGNAL(clicked()),this,SLOT(slottestHungrySingleton()));
connect(m_hungrysetvalbtn1,SIGNAL(clicked()),this,SLOT(slottestHungrySingletonval1()));
connect(m_hungrysetvalbtn2,SIGNAL(clicked()),this,SLOT(slottestHungrySingletonval2()));
}
Widget::~Widget()
{
}
void Widget::slottestLazySingleton()
{
LazySingleton::getinstance()->testfunc();
}
void Widget::slottestLazySingletonval1()
{
LazySingleton::getinstance()->setval(1);
}
void Widget::slottestLazySingletonval2()
{
LazySingleton::getinstance()->setval(1);
}
void Widget::slottestHungrySingleton()
{
HungrySingleton::getinstance()->testfunc();
}
void Widget::slottestHungrySingletonval1()
{
HungrySingleton::getinstance()->setval(1);
}
void Widget::slottestHungrySingletonval2()
{
HungrySingleton::getinstance()->setval(1);
}