这里主要讨论设计模式中单例模式的实现模板。
简介
有些时候,我们可能期望某个class在整个程序中只能被实例化一次(例如:帮助窗口类、工厂类)。单例模式的目标就是解决这个问题。通过巧妙的设计结构(禁止new,用static保存一个实例),能实现这种功能。虽然看起来极其简单,但考虑到代码健壮性(例如:线程安全),具备一定的技巧。下面是一个例子,
/* 单例模式例子 */
#include <mutex>
#include <iostream>
class Singleton{
public:
static Singleton* get_instance();
private:
static Singleton *instance_;
static std::mutex mutex_; //实例锁,用于线程安全
Singleton(){} // 禁用构造函数
};
Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::mutex_;
Singleton* Singleton::get_instance(){
// 双重nullptr检查。当实例已经创建后,外层检查可以避免实例获取过程中的锁操作
if(nullptr==instance_){
// 锁用于线程安全
std::unique_lock<std::mutex> lock(mutex_);
// 内层nullptr检查可以避免重复创建实例
if(nullptr==instance_){
instance_ = new Singleton();
}
}
return instance_;
}
int main(){
// 通过将构造函数设置为privete,禁止了用户创建实例
//Singleton *p0 = new Singleton();
Singleton *p1 = Singleton::get_instance();
Singleton *p2 = Singleton::get_instance();
if(p1==p2){
std::cout<<"p1==p2"<<std::endl;
}
return 0;
}
注意,nullptr是c++11的特性,它能区分不同类型的空指针(例如:flaot类型,int类型,char类型等)。
讨论
单例模式和工厂模式常常共用。在有些时候,我们需要在多个地方使用factory类来创建product类,但又没有必要创建多个工厂。此时可以考虑对factory类进行单例模式改造。
Reference
[1] 《大话设计模式》,程杰,第21章