前言
设计模式是一套被反复使用,多数人知晓,经过分类的,代码设计经验的总结。为什么会有设计模式这种东西呢?是人类历史发展中会产生兵法,最开始在原始部落时,部落之间战斗采用的都是原始的方式,比拼力量速度等,到了后来的春秋战国时,各国之间经常争斗,慢慢的就总结出了战斗的套路,后来的孙武就总结前人的经验,发挥自己的智慧写出了《孙子兵法》。
目录
1.设计模式:
使用设计模式是为了提高代码的可重用性,让代码更容易被他人理解,保证代码的可靠性。设计模式使代码编程真正工程化,设计模式是软件工程的基石脉络,如同摩天大楼的结构一样。
2.单例模式的两种实现
单例模式:
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在摸个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例获取这些配置信息,这种方法简化了在复杂环境下的配置管理。
2.1懒汉模式
如果单例对象的构造十分消耗时间,或者占用很多的资源,比如:加载插件,初始化网络,读取文件等等,而有可能 该对象的程序运行时用不到,那么程序在一开始就进行初始化,就会导致程序的启动非常的缓慢,所以这种情况使用懒汉模式(延迟加载)更好。
懒汉模式是在程序需要时候,才是进行相关的操作。
cpp
#include<mutex>
namespace qyy
{
//简化版的单例模式
class singleton
{
public:
static singleton* GetInstance()
{
if(_psingleton == nullptr)//双检查,可以防止有对象的情况下再去加锁减少资源的消耗
{
//这里存在线程安全的问题所以要加锁
unique_lock<mutex> lock(_mutex);//将锁交给智能指针进行管理,预防异常安全问题
//加锁
//_mutex.lock();
if (_psingleton == nullptr)
{
//这里可能存在异常安全的问题,所以加锁的时候可以将锁给智能指针
_psingleton = new singleton;
}
//_mutex.unlock();//解锁
}
return _psingleton;
}
//内置一个垃圾回收器
class GC
{
public://程序结束的时候自动回收资源
~GC()
{
if (_psingleton)
{
cout << "垃圾回收成功" << endl;
delete _psingleton;
}
}
};
static GC _gc;//定义一个静态的成员变量,程序结束的时候系统会自动调用。
private:
singleton(int a = 0)
:_a(a)
{}
//防拷贝
singleton(const singleton&);
singleton& operator=(const singleton&) = delete;
static singleton *_psingleton;//单例对象指针
int _a;
static mutex _mutex;
};
singleton* singleton::_psingleton = nullptr;//初始化指针
mutex singleton::_mutex;
singleton::GC _gc;
}
int main()
{
using namespace qyy;
singleton* p1 = singleton::GetInstance();
singleton* p2 = singleton::GetInstance();
singleton* p3 = singleton::GetInstance();
cout << p1 << endl << p2 << endl << p3;
return 0;
}
2.2饿汉模式
饿汉模式:就是不论你用不用,只要程序启动就会创建唯一的实例对象。
cpp
namespace qy
{
class singleton
{
public:
static singleton*& GetInstance()//直接返回就行
{
return _psingleton;
}
private:
singleton(int a = 0)
:_a(a)
{
}
//防拷贝
singleton(const singleton&);
singleton& operator=(const singleton&);
static singleton* _psingleton;//类对象的指针
int _a;
};
singleton* singleton::_psingleton = new singleton();//初始化时就定义好静态的对象
}
int main()
{
using namespace qy;
singleton* p1 = singleton::GetInstance();
singleton* p2 = singleton::GetInstance();
singleton* p3 = singleton::GetInstance();
cout << p1 << endl << p2 << endl << p3;
return 0;
}
2.3懒汉模式和饿汉模式的优缺点
1.懒汉模式需要考虑线程安全问题因此代码的实现较为复杂,饿汉模式不存在这样的问题,实现简单。
2.懒汉模式是一种懒加载需要时在初始化创建对象,不会影响程序的启动,饿汉模式则相反,程序启动阶段就创建实例化对象,会导致程序启动慢,影响体验,
3.如果有多个实例,假设实例A对实例B存在依赖关系(实例A的创建要等实例B创建以后才可以创建)那么这时候就不可以用饿汉模式,因为饿汉模式不能决定实例A和实例B的创建顺序。
4.如果单例中存在进程的创建等需要主函数运行起来以后才可以做的事情时,饿汉模式也是不可以使用的。