1.意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2.动机
对一些类来说,只有一个实例是很重要的。让类自身负责保存它唯一的实例,这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。
3.适用性
- 当类只能有一个实例而且客户可以从一个周所周知的访问点访问它时。
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
4.结构
5.代码实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <Windows.h> //静态成员实例的懒汉模式 class Singleton { public: static CRITICAL_SECTION gSection; static Singleton * GetInstance() { InitializeCriticalSection(&gSection); EnterCriticalSection(&gSection); if(NULL == m_pSingleton) { m_pSingleton = new Singleton(); } return m_pSingleton; LeaveCriticalSection(&gSection); } void Print() { std::cout<<"Singleton is Created"<<std::endl; } private: static Singleton* m_pSingleton; Singleton() { } }; CRITICAL_SECTION Singleton::gSection; Singleton* Singleton::m_pSingleton = NULL;
注意此实例的构造函数为私有的以防止使用时实例化此类。此实例加了临界区(也可加锁)以保证单例的线程安全,频繁加锁可能会有性能问题(处理大量数据时)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class SingletonInside { public: static CRITICAL_SECTION CriticalSection; static SingletonInside * GetInstance() { InitializeCriticalSection(&CriticalSection); EnterCriticalSection(&CriticalSection); static SingletonInside instace; return &instace; LeaveCriticalSection(&CriticalSection); } void Print() { std::cout<<"SingletonInside is Created"<<std::endl; } private: SingletonInside() { } }; CRITICAL_SECTION SingletonInside::CriticalSection;
此内部静态变量只会初始化一次,因此每次获取实例时,获取的为同一个实例。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class SingletonStatic { public: static const SingletonStatic * GetInstance() { return m_SingletonInstance; } void Print() { std::cout<<"SingletonStatic is Created"<<std::endl; } private: static const SingletonStatic * m_SingletonInstance; SingletonStatic() { } }; const SingletonStatic* SingletonStatic::m_SingletonInstance = new SingletonStatic();
静态成员初始化在进入main函数之前已经完成,此种实现没有争夺锁的性能问题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "Singleton.h" int main() { auto pSingltonInstacne = Singleton::GetInstance(); pSingltonInstacne->Print(); auto pSingltonInside = SingletonInside::GetInstance(); pSingltonInside->Print(); auto pSingltonStatic = SingletonStatic::GetInstance(); pSingltonStatic->Print(); while(1); }
6.测试结果
7.效果
- 对唯一实例的受控访问
- 缩小名空间
- 允许对操作和表示的精化
- 允许可变数目的实例
- 比类操作更灵活