c++设计模式一:单例模式

        使用场景:确保只有一个类对象存在,避免此类被多次实例化。

        比如软件中有个按钮,按下后弹出一个对话框,对话框中要显示一大堆数据,这些数据需要从一个文件中读取出来,用户选择一种后窗口消失,再次按下再次弹出。

        很明显,每次弹窗都需要读取一次,效率极低,这个时候就需要写一个读取文件的类,将其设置为单例模式,只需读取一次,后续直接从内存中读取,可大大提高效率。

        这里先写一个简单的“懒汉式”单例:

class LoadData
{
public:
	LoadData();
	~LoadData();

	QString getData();

	static LoadData* getInstance();
	static LoadData* m_loader;

private:
	QString m_data;
};
#include "LoadData.h"

LoadData* LoadData::m_loader = nullptr;
LoadData::LoadData()
{
	//这里假装有一大堆读取数据的代码
	m_data = "Hello world!";
}


LoadData::~LoadData()
{
}

LoadData* LoadData::getInstance()
{
	if (m_loader ==nullptr)
	{
		m_loader = new LoadData();
	}
	return m_loader;
}
LoadData* ld = LoadData::getInstance();
for (int i = 0; i < 10;i++)
{
	qDebug << ld->getData();
}

        当第一次调用时走构造函数读取一次,后面的调用直接返回。所以懒汉式单例就是被调用时才将数据加载到内存中,如果对这个类使用频率不高时可使用这种方式。优点就是使用时才开销内存,缺点就是第一次调用耗时较长。

        下面将其改为“恶汉式”单例:

        初始化时直接new:

LoadData* LoadData::m_loader = new LoadData();

        去掉判空操作:

LoadData* LoadData::getInstance()
{
	/*if (m_loader ==nullptr)
	{
		m_loader = new LoadData();
	}*/
	return m_loader;
}

        这样程序加载时自动将数据读取到内存中,调用时已经读过了,所以避免了第一次慢的问题。优点当然是调用时不费时,缺点是程序加载过程中就将数据加载到内存中,增加了内存的开销,如果程序中对此类调用频繁可使用此种方式。

        到这里看似很简单,基本都实现了,其实还有很多问题:

        1.如何防止别人直接构建类对象:

LoadData ld;//直接调用构造函数,还是每次都要读取,无法实现单例特性

        解决方案:不让别人访问构造函数,将构造函数和类对象指针私有化:

private:
	static LoadData* m_loader;
	LoadData();

        2.如何防止别人调用getinstance后解引用后拷贝给一个对象:

LoadData ld= *LoadData::getInstance();

        解决方案:将拷贝构造函数私有化或者使用c++11特性设置为delete:

LoadData(const LoadData& loader) = delete;

        3.如何防止调用两次getinstace后互相赋值问题:

LoadData* ld1 = LoadData::getInstance();
LoadData* ld2 = LoadData::getInstance();
*ld1 = *ld2;

        解决方案将赋值操作符重载函数私有化或delete:

LoadData& operator=(const LoadData& loader) = delete;

        4.如何防止多线程场景中被多次初始化?

        解决方法:加双检锁

#include "mutex"
std::mutex rs_mutex;
LoadData* LoadData::m_loader = new LoadData();

LoadData* LoadData::getInstance()
{
	if (m_loader==nullptr)
	{
		std::unique_lock myMutex(rs_mutex);
		if (m_loader == nullptr)
		{
			m_loader = new LoadData();
		}
	}
	return m_loader;
}

最后完整版代码:

#include 
class LoadData
{
public:
	QString getData();
	static LoadData* getInstance();
	LoadData(const LoadData& loader) = delete;
	LoadData& operator=(const LoadData& loader) = delete;
private:
	static LoadData* m_loader;
	LoadData();
private:
	QString m_data;
};
#include "LoadData.h"
#include "iostream"
#include "mutex"
std::mutex rs_mutex;
LoadData* LoadData::m_loader = new LoadData();

LoadData::LoadData()
{
	//这里假装有一大堆读取数据的代码
	m_data = "Hello world!";
}


LoadData* LoadData::getInstance()
{
	if (m_loader==nullptr)
	{
		std::unique_lock myMutex(rs_mutex);
		if (m_loader == nullptr)
		{
			m_loader = new LoadData();
		}
	}
	return m_loader;
}

        参考:慕课网轻松学习23中c++设计模式课程

        参考文献:c++ 单例模式与多线程_c++ 单例模式 多线程_师范大学生的博客-CSDN博客

你可能感兴趣的:(c++设计模式,设计模式,c++)