C++ 设计模式之单例模式
设计模式 : 大佬们总结出的是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
今天讲一讲,设计模式中创建型模式的单例模式(创建型模式还有工厂方法模式、抽象工厂模式、建造者模式、原型模式)
单例模式: 通俗地说,一个类只能创建一个对象
特点: 1.该模式下保证系统中该类只有一个实例,
2. 提供一个全局访问点
3. 该实例被所有程序共享
C++实现:
单线程模式下的单例模式
class Singleton { public: static Singleton* GetInstance() { if(m_instance==NULL) { m_instacne = new Singleton(); } return m_instance; } private: Singleton(){} Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton* m_instance; }; Singleton* Singleton::m_instance =NULL;
那么他是怎么完成单例模式的条件呢?
1. 私有构造,拷贝和赋值函数 --- 外界无法通过new创建对象
2. 静态成员函数 --- 全局唯一访问点
为什么是静态成员变量? 静态成员函数只能调用静态成员变量,并且静态成员变量必须在类外完成初始化。
我们会发现,如果在多线程模式下,如果两个线程同时访问入口点,就会创建出两个!
接下来介绍能保证线程安全的两种经典的单例模式:
懒汉模式 --- 程序在需要的时候才创建实例 (人如其名,到了吃饭的时候才起床,是不是和你一样~)
class Singleton { public: static Singleton* GetInstance() { if(m_instance==NULL){ Lock(); if(m_instance==NULL) { m_instacne = new Singleton(); } return m_instance; } } private: Singleton(){} Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton* m_instance; };
Singleton* Singleton::m_instance =NULL;
我们发现,单例模式一般情况下用的都是懒汉模式,但是懒汉模式使用了加锁进行互斥操作
那么为什么要判断两次?
第一个判断 --- 提高效率,防止加锁影响效率
第二个判断 --- 防止创建两个实例,如果两个线程同时访问,都到了加锁这里,那么当第一个线程释放锁的时候,第二个线程就会进去,不判断就会创建两个。
应用场景: 对实例访问量小的项目 --- 时间换空间
饿汉模式 --- 程序在开始就生成实例(还没睡醒,就饿得起床去吃饭了,大概昨天没吃晚饭吧~)
class Singleton { public: static Singleton* GetInstance() { return singleton; } private: Singleton() {} static Singleton *singleton; }; Singleton* Singleton::GetInstance() { return singleton; } Singleton* Singleton::singleton = new Singleton();
如何保证线程安全?
程序在进入主函数之前就由主线程以单线程的方式完成了
应用场景: 对实例访问量大的项目 --- 空间换时间