「 设计模式 」可复用面向对象软件的基础
整理 | 猿胖子
出品 | 猿武场(ID:apesarena)
关注公众号并回复数字「 1024 」加入猿武场微信社群
本系列文章中所讲解的设计模式均采用C++语言表述。
概念与意图
使用场景
对于某些类来说,只有一个实例是很重要的。例如如下某些场景:
系统中可以有多个打印机,但却只应该有一个printer spooler (打印假脱机) ,以避免两个打印作业同时输出到打印机
系统中只应该有一个文件系统和一个窗口管理器
应用软件系统中的日志应用,保证仅有一个实例去操作

怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?全局变量使得一
个对象可以被访问,但它不能防止我们实例化多次这个对象。
适用性
在如下情况下可以使用 SingIeton(单例)模式:
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时
参与者
定义一个 Instance 操作,允许客户访问它的唯一实例。 Instance 是一个类的中的一个静态成员函数
可能负责创建它自己的唯一实例
SingIeton(单例)模式优点
对唯一实例的受控访问 因为 Singleton 类封装它的唯一实例,所以它可以严格的控制客户怎样以何时访问它
允许对操作和表示的精化 Singleton 类可以有子类,而且用这个扩展类的实例来配置一个应用非常容易
允许可变数目的实例 这个模式使得我们更易于改变想法,并 允许 Singleton 类的多个实例。此外,我们还可以用相同的方法来控制应用所使用的实例数目。只有允许访问 Singleton 类的操作需要改变
比类操作更灵活 另一种封装单例功能的方式是使用类操作(即C++中的静态成员函数)。但这种设计难以改变设计以允许一个类有多个实例,此外C++中的静态成员函数不是虚函数,其子类不能多态地重定义

具体实现
在使用 SingIeton(单例)模式时所需要考虑的实现问题是保证一个唯一的实例。做到这一点的一个常用方法是将创建这个实例的操作隐藏在一个类操作(即一个静态成员函数或者是一个类方法)后面,由它保证只有一个实例被创建。
// singleton.h
class Singleton : public QObject
{
Q_OBJECT
public:
static Singleton* Instance();
protected:
explicit Singleton(QObject *parent = nullptr);
public:
void test();
private: static Singleton* _instance;
signals:
};
// singleton.cpp
Singleton* Singleton::_instance = 0;
Singleton *Singleton::Instance()
{
if(_instance == 0){
_instance = new Singleton;
}
return _instance;
}
void Singleton::test()
{
qDebug() <<" this is test !";
}
// to test
Singleton::Instance()->test();
在QT中的另一种实现
使用QT提供的宏 Q_GLOBAL_STATIC 可以方便地创建线程安全的全局静态对象
// singleton.h
class Singleton : public QObject
{
Q_OBJECT
public:
static Singleton* Instance();
public:
explicit Singleton(QObject *parent = nullptr);
public:
void test();
signals:
};
// singleton.cpp
#include <QGlobalStatic>Q_GLOBAL_STATIC(Singleton,singleton)Singleton *Singleton::Instance()
{return singleton();
}
void Singleton::test()
{
qDebug() <<" this is test !";
}
// to test
Singleton::Instance()->test();
需要注意将 Q_GLOBAL_STATIC 宏放置于源文件且非函数体中,否则会编译错误。由于生成的对象具有静态链接,如被多个源文件包含将导致被多次定义。

注公众号并回复数字「 1024 」加入猿武场微信社群
欢迎加入程序员社群,更多技术摘要等你拿走
社群福利:
1. 行业大牛技术手札,知识点汇总;
2. 求职/招聘信息内推;
4. 人际交往,增强技术宅人际交流;
5. 调节繁杂无趣的闲暇时光;
6. 不定期线上周边於线下技术活动沙龙。





