【设计模式】设计模式C++编程实现之单例模式(Singleton Pattern)

8 篇文章 0 订阅
有一些对象我们只需要一个,比如说线程池(threadpool)缓存(cache)、对话框、处理偏好设置和注册表的对象、日志对象,充当打印机、显卡等设备的驱动程序的对象。如果制造出多个实例,则会导致许多问题的产生。
许多时候的确可以通过程序员之间的阅读就可以办到,但是利用单例模式是更好的办法。
单例模式给我们一个全局的访问点,和全局变量一样方便,有没有全局变量的缺点(必须在程序开始就创建,如果后面没有用到,会造成资源的浪费)。

单件模式的定义:
确保一个类只有一个实例,并提供一个全局访问点。

UML图如下:

图一 单例模式UML图

单件模式实现方式:
将构造函数声明为私有的,在类中定义一个静态成员变量记录类的唯一实例。定义一个静态public方法来实例化对象,并返回这个实例。在这个方法中实行延迟化策略。如果我们不需要这个实例,就永远不会实例化它。在外部只能通过调用这个方法来实例化对象。

经典单件模式C++代码实现:
  1. //单例模式  
  2. #include <iostream>  
  3.   
  4. using namespace std;  
  5.   
  6. //经典单例模式实现  
  7. class Singleton{  
  8. private:  
  9.     static Singleton *uniqueInstance;//利用一个静态变量来记录Singleton的唯一实例  
  10.     Singleton(){};  
  11.   
  12. public:  
  13.     //实例化对象的方法  
  14.     static Singleton* getInstance()  
  15.     {  
  16.         if(NULL == uniqueInstance)  
  17.             uniqueInstance = new Singleton();  
  18.         return uniqueInstance;  
  19.     }  
  20. };  
  21.   
  22. Singleton* Singleton::uniqueInstance = NULL;//静态成员变量初始化  
  23.   
  24. int main()  
  25. {  
  26.     Singleton *singletonObj = Singleton::getInstance();  
  27.   
  28.     delete singletonObj;  
  29.   
  30.     return 0;  
  31. }  

当在多线程环境下使用单件模式时,可能会出现问题。问题出在函数getInstance(),没有实现同步。

解决方法:
(1)加同步锁
加锁来实现多个线程判断instance是否为空以及创建实例正常进行。代码如下:
  1. class SingletonPattern{  
  2. private:  
  3. static SingletonPattern *instance;//静态类型的实例  
  4. SingletonPattern(){}//构造函数  
  5.   
  6. public:  
  7. static SingletonPattern *getInstance(){  
  8. Lock();//加锁函数  
  9. if (NULL == instance)//延迟初始策略  
  10. {  
  11. instance = new SingletonPattern();  
  12. }  
  13. UnLock();//释放锁函数  
  14.   
  15. return instance;  
  16. }  
  17. };  

但是可能会造成程序运行效率的急剧下降。


(2)双重检查加锁
我们可以针对上面一种加同步锁的方法进行优化。
因为只有当实例还没有创建之前需要进行加锁操作,以保证只有一个线程创建出实例。而当实例已经被创建出之后,就不需要再做加锁操作了。
优化后的代码如下:
  1. class SingletonPattern{  
  2. private:  
  3. static SingletonPattern *instance;//静态类型的实例  
  4. SingletonPattern(){}//构造函数  
  5.   
  6. public:  
  7. static SingletonPattern *getInstance(){  
  8. if (NULL == instance)//延迟初始策略  
  9. {  
  10. Lock();//加锁函数  
  11. if (NULL == instance)  
  12. {  
  13. instance = new SingletonPattern();  
  14. }  
  15. UnLock();//释放锁函数  
  16. }  
  17. return instance;  
  18. }  
  19. };  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值