设计模式——单例模式
单例模式代码详细
单例的几种模式细致详解,见单例
涉及的单例指针,何时释放空间的问题,下面代码也给出答案。
这里给出模板的单例代码,使用的是双检查锁。
#ifndef SINGLETON_H //判断是否有这个头文件加进来了,有的话就增加,没有的话,跳过。
#define SINGLETON_H
#include <mutex>
//单例模板类
template <class T>
class Singleton
{
public:
static T* getInstance()
{
//这里用于初始化,从而能够在程序结束的时候,直接析构
//巧妙利用garbo类
m_garbo.init();
//判断是否第一次调用
if (m_pInstance == nullptr)
{
//这里双检查锁,为了更好的高并发功能,是懒汉实现
//外面if检查是否创建,没有则加锁创建
//其它线程同样可以加锁创建,但是加了锁后,只要执行了锁里面的内容,
//单例的指针就一定会被创建。当其它线程进入锁后,要么没创建,就自己创建;要么已经建好,就直接退出。
//从而可以高并发,但是这个也有缺陷。
m_locker.lock();
if (m_pInstance == nullptr)
{
m_pInstance = new T();
}
m_locker.unlock();
}
return m_pInstance;
}
protected:
//使继承者无法public构造函数和析构函数
//单例唯一,就不pubulic构造了;但是有继承,故而protected
Singleton() {}
~Singleton() {}
private:
//禁止拷贝构造和赋值运算符. The only way is getInstance()
//const Singleton& src 常引用对象,不改变值,但还使用引用,因为引用来的更快
//值传递更慢
Singleton(const Singleton& src) = delete;
Singleton &operator=(const Singleton& src) = delete;
//它的唯一工作就是在析构函数中析构Singleton的实例,所以private
class Garbo
{
public:
~Garbo()
{
//这里析构单例指针
if (Singleton::m_pInstance)
{
delete Singleton::m_pInstance;
Singleton::m_pInstance = nullptr;
}
}
void init()
{
}
};
private:
static std::mutex m_locker;
static T* m_pInstance;
static Garbo m_garbo;//类的静态成员变量,类内声明,但是类外需要定义,这里由于是用来析构单例的,所以需要类外定义
//但是,这个变量没有实际意义,也就是说我们业务不需要,所以设置为私有。
};
template <typename T>
std::mutex Singleton<T>::m_locker;
template <class T>
T* Singleton<T>::m_pInstance = nullptr;
template <class T>
typename Singleton<T>::Garbo Singleton<T>::m_garbo; //这里是类外的定义,分配的是栈空间,最后程序结束,操作系统会回收它,从而带动单例析构,释放空间。
#endif // SINGLETON_H