设计模式
创建型、结构型、行为型
单例模式:创建型
定义:
只提供唯一一个类的实例,本质就是一个全局变量
用途:
①设备管理器:在类里面管理设备驱动
②数据池:多个函数对其数据进行读写操作
要点:
1、static特性,全局只有一个实例,并且用户自己不能声明定义,即将构造函数设为私有private。
2、线程安全
3、禁止赋值和拷贝
实现
1、饿汉式
从名字上也很好理解,就是“比较勤”,实例在初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。好处是没有线程安全的问题,坏处是浪费内存空间。
class test
{
public:
//3、引用返回一个实例
static test& getinst()
{
return m_inst;
}
private:
//1、构造方法私有
test()
{}
private:
//2、成员变量包含一个static的自身的实例
static test m_inst;
};
//4、初始化单例对象
test test::m_inst;
2、懒汉式
再需要实例化的时候才进行实例化,即get_instance() 方法的时候才 new 一个单例的对象, 如果不被调用就不会占用内存。
缺点:
- 线程安全:当多线程获取单例时有可能引发竞态条件;解决办法:加锁
- 内存泄漏:类中只负责new出对象,却没有负责delete对象,因此只有构造函数被调用,析构函数却没有被调用;因此会导致内存泄漏。解决办法: 使用共享指针;
//懒汉
class test
{
public:
//3、返回创建完毕的指针
static test* getinst()
{
if (m_inst == nullptr)
{
m_inst = new test;
}
return m_inst;
}
private:
//1、构造方法私有
test()
{}
private:
//2、此处不再是实例,而是指针
static test *m_inst;
};
//4、初始化为空指针
test* test::m_inst = nullptr;
3、双检锁
上面的单例类有一个缺陷,就是在多线程的时候不安全,所以可以对其改进。
又叫双重校验锁,综合了懒汉式和饿汉式两者的优缺点整合而成。看上面代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。
#include<mutex>
mutex mt;
//双检锁
class test
{
public:
//3、返回创建完毕的指针
static test* getinst()
{
if (m_inst == nullptr)
{
//5、加锁解锁
mt.lock();
if (m_inst == nullptr)
{
m_inst = new test;
}
mt.unlock();
}
return m_inst;
}
private:
//1、构造方法私有
test()
{}
private:
//2、此处不再是实例,而是指针
static test *m_inst;
};
//4、初始化为空指针
test* test::m_inst = nullptr;
4、静态内部类
静态内部类的方式效果类似双检锁,但实现更简单。但这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用
5、枚举
枚举的方式是比较少见的一种实现方式,但是看上面的代码实现,却更简洁清晰。并且她还自动支持序列化机制,绝对防止多次实例化。