单例模式
2021-12-13
4 min read
单例模式
目的与概念
在开发中有时会需要确保系统中某一个类只有一个对象实例,并提供一个全局访问点以被所有模块共享,这应由对象提供者而不是使用者来保证;
例如:日志系统应只有一个,若有多个的话,可能会导致日志的混乱,而日志模块的提供者有责任约束其使用者,确保使用者的程序中只能有一个日志系统实例;
实现上述目的的方法就是单例模式。单例模式实际上是对唯一变量的一种封装,约束了其使用方式,让开发者更方便更安全地访问此变量;同时其可以让单例对象如同普通对象一样,作为参数在其他模块中使用,而其他模块不必知道其是否是单例;
单例模式恰当使用可以起到良好的效果,但是过度使用反而会阻碍程序的解耦,所以在实际使用中需要仔细考量;
根据单例对象构建的时机的不同,可将单例模式分为两种:
- 懒汉方式,在首次使用时构建单例对象,即用时间换空间;
- 饿汉方式,在程序启动时构建单例对象,即用空间换时间;
代码示例
懒汉方式与饿汉方式的代码描述如下所示:
- 懒汉方式:
// ----------------------------------------------------------------------------
/**
* @file Singleton.h
*/
// 本例中使用 Scott Meyers,《Effective C++》 中的 Singleton,这种方式在C++11之后保证线程安全。
class Singleton {
public:
Singleton(const Singleton& rhs) = delete;
Singleton& operator=(const Singleton& rhs) = delete;
Singleton(Singleton&& rhs) = delete;
Singleton& operator=(Singleton&& rhs) = delete;
~Singleton() {}
static Singleton& getInstance() {
static Singleton s_instance;
return s_instance;
}
private:
Singleton() {}
// 其他非静态成员变量
// ...
};
// ----------------------------------------------------------------------------
/**
* @file main.cpp
*/
// 调用代码
#include "Singleton.h"
int main()
{
// 类型为引用
Singleton & singleInst = Singleton::getInstance();
// ...
return 0;
}
- 饿汉方式:
// ----------------------------------------------------------------------------
/**
* @file Singleton.h
*/
// 此方式无需担心线程安全性问题,但是可能存在初始化顺序不确定问题
class Singleton {
public:
Singleton(const Singleton& rhs) = delete;
Singleton& operator=(const Singleton& rhs) = delete;
Singleton(Singleton&& rhs) = delete;
Singleton& operator=(Singleton&& rhs) = delete;
~Singleton() {}
static Singleton& getInstance() {
return s_instance;
}
private:
Singleton() {}
static Singleton s_instance;
// 其他非静态成员变量
// ...
};
// ----------------------------------------------------------------------------
/**
* @file Singleton.cpp
*/
// 静态变量类外初始化
#include "Singleton.h"
Singleton Singleton::s_instance = {};
// ----------------------------------------------------------------------------
/**
* @file main.cpp
*/
// 调用代码
#include "Singleton.h"
int main()
{
// 类型为引用
Singleton & singleInst = Singleton::getInstance();
// ...
return 0;
}
Qt中的单例模式
单例模式使用十分广泛,例如 Qt 中 QCoreApplication 的实现也使用了单例模式,其代码片段如下:
// ----------------------------------------------------------------------------
/**
* @file qapplication.h
* @note 引自 Qt 库中的 include/QtCore/qapplication.h
*/
#if defined(qApp)
#undef qApp
#endif
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
// ...
// ----------------------------------------------------------------------------
/**
* @file qcoreapplication.h
* @note 引自 Qt 库中的 include/QtCore/qcoreapplication.h
*/
class QCoreApplication {
// ...
static QCoreApplication *instance() { return self; }
// ...
private:
// ...
static QCoreApplication *self;
Q_DISABLE_COPY(QCoreApplication)
// ...
};
// ----------------------------------------------------------------------------
/**
* @file main.cpp
*/
// 调用代码
#include <QApplication>
#include <QString>
int main()
{
// ...
QString sheetStr = qApp->styleSheet();
qDebug() << sheetStr;
// ...
return 0;
}
参考
- 《设计模式--可复用面向对象软件的基础》,GoF,机械工业出版社,2000年09月;
- 《C++设计模式》课程,李建忠主讲;
- 《C++ 单例模式》博客, <Arkin> ;
版权声明:
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!