今天我们不举实际的例子了,就直接开始讨论单件模式吧,首先我们要明白什么叫单件模式。
单件模式:确保一个类只有一个实例,并提供一个全局访问点。
在写程序的过程中,很多时候我们需要用到一个全局对象,很好,当我们需要使用全局对象的时候我们的单件模式就排上用场了,废话不多说,我们直接看代码。
class Singleton
{
public:
static Singleton* getSingleton()
{
if (m_singleton == nullptr)
{
m_singleton = new Singleton;
}
return m_singleton;
}
static void clear()
{
if (m_singleton != nullptr)
{
delete m_singleton;
m_singleton = nullptr;
}
}
private:
Singleton() = default;
virtual~Singleton() {};
Singleton operator=(const Singleton &) {}
Singleton(const Singleton &other) {}
private:
static Singleton *m_singleton;
};
Singleton* Singleton::m_singleton = nullptr;
接下来我们分析一下上面Singleton这个类,首先我们将构造函数,copy构造函数,重载=全部定义为私有方法,这样是为了放在在该类外构造、拷贝或者复制该类的对象。
我们提供了两个静态方法,分别用来生成以及删除该单件中的数据对象,看到这里聪明的你可能已经看出来了,这个设计存在一个明显的问题,那就是如果我们再多线程中调用getSingleton函数可能会new多次,造成内存泄漏,为了解决这个问题我们有以下几种解决方案。
方案一、加锁
我们只需要经过以下修改即可
#include <memory>
#include <mutex>
#include <thread>
using namespace std;
class Singleton
{
public:
static Singleton* getSingleton()
{
m_creatMutex->lock();
if (m_singleton == nullptr)
{
cout << "1" << endl;
m_singleton = new Singleton;
}
m_creatMutex->unlock();
return m_singleton;
}
static void clear()
{
if (m_singleton != nullptr)
{
delete m_singleton;
m_singleton = nullptr;
}
}
private:
Singleton() = default;
virtual~Singleton() {};
Singleton operator=(const Singleton &) {}
Singleton(const Singleton &other) {}
private:
static Singleton *m_singleton;
static mutex *m_creatMutex;
};
Singleton* Singleton::m_singleton = nullptr;
mutex* Singleton::m_creatMutex = new mutex;
方案二、在程序运行前便将单件对象创建好。
Singleton* Singleton::m_singleton = new Singleton;
当然这样还存在一个问题,那就是在程序运行期间不能删除单件中保存的对象,否则仍会存在该问题。
一般面对多线程的时候我们都会采用加锁的方式解决。