设计模式-单例模式
简单介绍
- 单例模式是为某个类创建全局唯一的静态实例
- 通过维护一个 static 的成员变量来记录这
个唯一的对象实例。通过提供一个 staitc 的接口 instance 来获得这个唯一的实例。
类图
代码
懒汉模式:第一次用到类的实例的时候才回去实例化。
版本一:存在线程安全问题以及内存泄漏问题
class singleton //实现单例模式的类
{
private:
private:
Singleton(){}//构造
Singleton(const Singleton &clone){} //拷⻉构造
Singleton& operator=(const Singleton&) {}
static Singleton * _instance;
public:
static singleton* GetInstance()
{
if (Instance == NULL) //判断是否第一调用
Instance = new singleton();
return Instance;
}
};
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
版本二:存在线程安全问题无内存泄漏问题
class Singleton {
public:
static Singleton * GetInstance() {
if (_instance == nullptr) {
_instance = new Singleton();
atexit(Destructor); //程序退出时调用Destructor函数
}
return _instance;
}
~Singleton() {}
private:
static void Destructor() {
if (nullptr != _instance) {
delete _instance;
_instance = nullptr;
}
}
Singleton();//构造
Singleton(const Singleton &cpy); //拷⻉构造
Singleton& operator=(const Singleton&) {}
static Singleton * _instance;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
// 还可以使⽤ 内部类,智能指针来解决; 此时还有线程安全问题
版本三:无线程安全问题无内存泄漏问题,但存在指令重排序问题
#include <mutex>
class Singleton { // 懒汉模式 lazy load
public:
static Singleton * GetInstance() {
//std::lock_guard<std::mutex> lock(_mutex); // 3.1 切换线程
if (_instance == nullptr) {
std::lock_guard<std::mutex> lock(_mutex); // 3.2
if (_instance == nullptr) {
_instance = new Singleton(); //指令重排序
atexit(Destructor);
}
}
return _instance;
}
private:
static void Destructor() {
if (nullptr != _instance) {
delete _instance;
_instance = nullptr;
}
}
Singleton(){} //构造
Singleton(const Singleton &cpy){} //拷⻉构造
Singleton& operator=(const Singleton&) {}
static Singleton * _instance;
static std::mutex _mutex;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化
版本四:无线程安全问题无内存泄漏问题,无指令重排序问题
#include <mutex>
#include <atomic>
class Singleton {
public:
static Singleton * GetInstance() {
Singleton* tmp = _instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//获取内存屏障
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(_mutex);
tmp = _instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存屏障
_instance.store(tmp, std::memory_order_relaxed);
atexit(Destructor);
}
}
return tmp;
}
private:
static void Destructor() {
Singleton* tmp = _instance.load(std::memory_order_relaxed);
if (nullptr != tmp) {
delete tmp;
}
}
Singleton(){}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
static std::atomic<Singleton*> _instance;
static std::mutex _mutex;
};
std::atomic<Singleton*> Singleton::_instance;//静态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化
// g++ Singleton.cpp -o singleton -std=c++11
版本五:解决版本四的代码繁琐问题,但将对象创建到了全局区,全局区空间有限
// c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发
线程将会阻塞等待初始化结束。
class Singleton
{
public:
~Singleton(){}
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
private:
Singleton(){}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
};
// 继承 Singleton
// g++ Singleton.cpp -o singleton -std=c++11
/*该版本具备 版本5 所有优点:
1. 利⽤静态局部变量特性,延迟加载;
2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函数;
3. 静态局部变量初始化时,没有 new 操作带来的cpu指令reorder操作;
4. c++11 静态局部变量初始化时,具备线程安全;
*/
版本六:支持模板的单例模式
template<typename T>
class Singleton {
public:
static T& GetInstance() {
static T instance; // 这⾥要初始化DesignPattern,需要调⽤
//DesignPattern 构造函数,同时会调⽤⽗类的构造函数。
return instance;
}
protected:
virtual ~Singleton() {}
Singleton() {} // protected修饰构造函数,才能让别⼈继承
Singleton(const Singleton&) {}
Singleton& operator =(const Singleton&) {}
};
class DesignPattern : public Singleton<DesignPattern> {
friend class Singleton<DesignPattern>; // friend 能让 Singleton<T> 访
//问到 DesignPattern构造函数
private:
DesignPattern(){}
DesignPattern(const DesignPattern&) {}
DesignPattern& operator=(const DesignPattern&) {}
}
饿汉模式:程序开始运行时就加载完成
class singleton //实现单例模式的类
{
private:
singleton() {} //私有的构造函数
singleton(const singleton&) {}
singleton& operator =(const singleton&) {}
static singleton *Instance = new singleton ;
public:
static singleton* GetInstance()
{
return &Instance;
}
};