常见单例模式

设计模式

创建型、结构型、行为型

单例模式:创建型

定义:

只提供唯一一个类的实例,本质就是一个全局变量

用途:

①设备管理器:在类里面管理设备驱动
②数据池:多个函数对其数据进行读写操作

要点:

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 一个单例的对象, 如果不被调用就不会占用内存。
缺点:

  1. 线程安全:当多线程获取单例时有可能引发竞态条件;解决办法:加锁
  2. 内存泄漏:类中只负责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、枚举

枚举的方式是比较少见的一种实现方式,但是看上面的代码实现,却更简洁清晰。并且她还自动支持序列化机制,绝对防止多次实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值