前言
设计模式(Design Pattern)是一套经过分类的,被反复使用的,代码设计经验的总结。 为什么会产生设计模式这个概念呢?随着时间的沉淀,以及前人的总结,我们发现代码设计也是有规律的,一类特定的问题会被一种特定的模式解决,这就衍生出了设计模式的概念。
使用设计模式的目的:为了代码的可重用性以及可靠性。
设计模式是软件工程的基石脉络,如同大厦的结构一样,设计模式使代码编写真正工程化。
一:单例模式
单例模式即一个类在全局中(进程)只能创建一个实例。
单例模式有两种实现模式:懒汉模式和饿汉模式。
1.1 懒汉模式
懒汉模式:第一次使用实例对象时再创建实例对象。
代码演示:
#include<iostream>
#include<thread>
#include<vector>
#include<mutex>
using namespace std;
class Singleton{
public:
// 静态成员函数只能访问静态成员变量
static Singleton* GetInstance(){
if (_pinst == nullptr)
// 局部域(通过作用域来控制解锁时机)
{
// _mtx.lock();
unique_lock<mutex> lock(_mtx); // (保护操作的原子性)
if (_pinst == nullptr)
// 锁只需要保护第一次(需要进行双检查)
_pinst = new Singleton;
// _mtx.unlock();
}
return _pinst;
}
Singleton(const Singleton& s) = delete;
// 实现一个内嵌垃圾回收类
class CGarbo {
public:
~CGarbo(){
if (Singleton::_pinst)
delete Singleton::_pinst;
}
};
// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
static CGarbo Garbo;
private:
// 构造函数私有化
Singleton(){}
// 防拷贝
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
static Singleton* _pinst;
static mutex _mtx;
};
Singleton* Singleton::_pinst = nullptr;
mutex Singleton::_mtx;
Singleton::CGarbo Garbo;
1.2 饿汉模式
饿汉模式:程序启动时就创建一个唯一的实例对象。
如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。
代码演示:
#include<iostream>
#include<thread>
#include<vector>
#include<mutex>
using namespace std;
// 饿汉模式
class Singleton
{
public:
static Singleton* GetInstance(){
return &m_instance;
}
private:
// 构造函数私有
Singleton(){};
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
// 单例对象
static Singleton m_instance;
};
// 在程序入口之前就完成单例对象的初始化,不用考虑线程安全的问题。
Singleton Singleton::m_instance;
1.3 懒汉模式和饿汉模式的对比
懒汉模式:
优点:懒汉模式在使用实例的时候才进行创建,不会影响程序的启动。并且多个单例实例启动顺序自由控制。
缺点:懒汉模式实现复杂。并且需要考虑线程安全问题
饿汉模式:
优点:饿汉模式实现简单,并且在程序启动时已经完成了对单例对象的初始化,不需要考虑线程安全问题。
缺点:饿汉模式在程序启动时完成了对单例对象的初始化,会在一定程度上影响程序启动。静态成员变量无法确定单例的创建初始化顺序,多个单例类对象实例启动顺序不确定。
小结:
实际中懒汉模式还是应用更为广泛