1.设计模式
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
一些设计理念:迭代器模式,配接器模式,单例模式,工厂模式,观察者模式
2.单例模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
使用样例:内存池的申请
1.饿汉模式
特点:
一开始(在main函数之前)就创造对象,就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象
缺点:
1.由于初始化在main函数之前,这样的类数据过多,会使得启动慢;
2.多个单例类有初始化依赖关系,饿汉模式无法控制类的初始化先后关系
class InfoSingleton
{
public:
static InfoSingleton& GetInstance()
{
return _sins;
}
void Insert(string name, int money)
{
_info[name] = money;
}
void Print()
{
for (auto kv : _info)
{
cout << kv.first << " " << kv.second << endl;
}
}
private:
InfoSingleton()
{}
InfoSingleton(const InfoSingleton& info) = delete;
InfoSingleton& operator=(const InfoSingleton& info) = delete;
map<string, int> _info;
private:
static InfoSingleton _sins;
};
InfoSingleton InfoSingleton::_sins;
int main()
{
InfoSingleton::GetInstance().Insert("张三", 1000);
InfoSingleton& info = InfoSingleton::GetInstance();
info.Insert("李四", 100);
//InfoSingleton copy = InfoSingleton::GetInstance(); //拷贝构造
//copy.Insert("***", 10000);
return 0;
}
2.懒汉模式
1.如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
2.如果类之间存在依赖关系,也可以使用懒汉模式(延迟加载)。
template<class Lock>
class LockGuard
{
public:
LockGuard(Lock& lk)
:_lk(lk)
{
_lk.lock();
}
~LockGuard()
{
_lk.unlock();
}
private:
Lock& _lk;
};
class _InfoSingleton
{
public:
//线程安全问题,多线程一起调用创建对象
static _InfoSingleton& GetInstance()
{
//双检查增加效率
if (_psins == nullptr) {
LockGuard<mutex> lock(*_smtx);
if (_psins == nullptr)
{
_psins = new _InfoSingleton;
}
}
return *_psins;
}
void Insert(string name, int money)
{
_info[name] = money;
}
void Print()
{
for (auto kv : _info)
{
cout << kv.first << " " << kv.second << endl;
}
}
private:
_InfoSingleton()
{}
_InfoSingleton(const _InfoSingleton& info) = delete;
_InfoSingleton& operator=(const _InfoSingleton& info) = delete;
map<string, int> _info;
private:
static _InfoSingleton* _psins;
static mutex* _smtx;
};
static _InfoSingleton* _psins = nullptr;
static mutex* _smtx;
1.这样写是懒汉模式,只创建一次,并且在main函数调用之后创建。
2.该代码有线程安全问题,在C++11后得到解决。
static _InfoSingleton& GetInstance()
{
static _InfoSingleton sinst;
return sinst;
}
注意:
1.懒汉模式需要注意线程安全问题,所以我们在类中需要有一个唯一的锁,确保判断时是串行访问的。
2.每次都先加锁再进行判断是否为空,其实是非常低效,所以我们需要双判断,第一次判断是为了抛去已经创建过的节省加锁的时间,第二次判断是为了创建对象使用的,而锁夹在中间确保第二次的判断是串行的。
3.饿汉模式不需要注意线程安全问题,因为饿汉在main调用之前就已经存在了,没有所谓的线程可以创建其他的对象。
3.单例对象释放问题
1.一般而言单例类不需要释放内存,因为单例出现的环境就是全局的,它的目的就是陪到进程执行到最后,那么其实不释放,进程结束后,操作系统也会将这一部分的资源回收。
2.特别的,如果我们需要在最后单例有一定要求,我们可以手写出析构,比如进程结束需要保存一些数据到文件中,那么我们析构可以手写要求。