(一)单例模式
在项目或面试中,最有可能遇到的就是单例模式,所以,能够手写一个单例模式是学习设计模式的基本功之一。
1. 单例模式
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。
所有的单例模式都是使用静态方法进行创建的,所以单例对象在内存中静态共享区中存储。
应用场景(参考:《大话设计模式》):
1) 需求:在前端创建工具箱窗口,工具箱要么不出现,出现也只出现一个
遇到问题:每次点击菜单都会重复创建“工具箱”窗口。
解决方案一:使用if语句,在每次创建对象的时候首先进行判断是否为null,如果为null再创建对象。
2) 需求:如果在5个地方需要实例出工具箱窗体
遇到问题:这个小bug需要改动5个地方,并且代码重复,代码利用率低
解决方案二:利用单例模式,保证一个类只有一个实例,并提供一个访问它的全局访问点。
单例模式可以分为懒汉式和饿汉式:
- 懒汉式:在类加载时不初始化。
- 饿汉式:在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。
2. 示例:双重校验锁
#ifndef SINGLETON_PATTERN_H
#define SINGLETON_PATTERN_H
#include <iostream>
#include <mutex>
class CSingleton
{
public:
/* 删除器类 */
class DeleteInstance
{
public:
~DeleteInstance()
{
std::cout << "DeleteInstance's destructor called." << std::endl;
if (CSingleton::m_pSingleton)
{
delete CSingleton::m_pSingleton;
}
}
};
static DeleteInstance deleteInstance; ///< 删除器类实例
public:
/* 获取实例的全局访问点 */
static CSingleton* GetInstance()
{
/* 双检锁 */
if (nullptr == m_pSingleton)
{
std::lock_guard<std::mutex> lgLock(m_mutex);
if (nullptr == m_pSingleton)
{
m_pSingleton = new CSingleton();
}
}
return m_pSingleton;
}
///* destructor */
//~CSingleton()
//{
// std::cout << "CSingleton's destructor called." << std::endl;
// delete m_pSingleton;
//}
private:
/* private constructor */
CSingleton()
{
std::cout << "CSingleton's constructor called." << std::endl;
}
/* private copy constructor */
CSingleton(const CSingleton&) = delete;
/* private operator = */
CSingleton& operator=(const CSingleton&) = delete;
private:
static CSingleton *m_pSingleton; ///< 静态实例
static std::mutex m_mutex; ///< 多线程时的单例, 保证线程安全
};
/* static 成员的初始化, 这些东西最好放在CPP文件中, 以免会产生重复定义问题 */
CSingleton* CSingleton::m_pSingleton = nullptr; ///< 懒汉式, 在第一次被引用时,才会实例化.
std::mutex CSingleton::m_mutex; ///< static mutex 初始化
CSingleton::DeleteInstance CSingleton::deleteInstance; ///< 删除器, 在程序结束时调用析构函数, 删除 m_pSingleton.
#endif // SINGLETON_PATTERN_H