C++单件模式

来源:互联网 发布:asp显示数据库内容 编辑:程序博客网 时间:2024/06/06 00:02

单件模式应该是所有设计模式中最简单的一个了,但是如果使用不当会出现很多问题,下面我们就分析一下单件模式

作用:保证一个class只有一个实体(instance),并为它提供一个全局唯一的访问点

 适用性:

1、对于一个类(对象),如果它比较大(占用的系统资源非常多),而且这些资源可以被全局共享,则可以设计为singleton模式。
2、对于一个类,需要对实例进行计数。可以在Instance中进行,并可以对实例的个数进行限制。
3、对于一个类,需要对其实例的具体行为进行控制,例如,期望返回的实例实际上是自己子类的实例。这样可以通过Singleton模式,对客户端代码保持透明。

首先看一下单件模式的通用写法(注意可能会存在问题的,就看你怎么使用了)

[cpp] view plaincopy
  1. //设计模式之单件模式  
  2. /* 
  3. 作用:保证一个class只有一个实体(instance),并为它提供一个全局唯一的访问点 
  4. */  
  5. class singleton  
  6. {  
  7. public:  
  8.     ~singleton()  
  9.     {//析构时使用  
  10.     }  
  11.     static singleton* getInstance()  
  12.     {  
  13.         if(_instance == NULL)  
  14.         {  
  15.             _instance = new singleton();  
  16.         }  
  17.         return _instance;  
  18.     }  
  19.   
  20. private:  
  21.     static singleton *_instance;  
  22.   
  23. private:  
  24. //最好将所有此类的实例化的进口全部堵死  
  25.     singleton()  
  26.     {  
  27.   
  28.     }  
  29.     singleton(const singleton&)  
  30.     {  
  31.   
  32.     }  
  33.     singleton& operator=(const singleton &)  
  34.     {  
  35.   
  36.     }  
  37. };  
  38. singleton *singleton::_instance = NULL;  

使用时,只需要调用singleton::getInstance()既可以获取到singleton的指针使用了,但是需要注意的一点是使用完成后需要调用delete singleton::getInstance();以便释放资源。

我们来分析一下上面的代码:

1、需要手动释放_instance,尤其是做接口时,需要告知使用方调用delete singleton::getInstance();语句。

2、如果在多线程环境下使用,问题更大了,如果大量线程调用到new时,可能会造成内存泄露,并且有可能前后获取的singleton对象不一致。

分析出了上面代码的问题,那我们应如何解决他们?

针对问题1:释放

1、调用delete singleton::getInstance();

2、注册atexit()函数,将释放内存的方法放入到atexit函数中,此种方法可以将多个单件放在一起调用。

[cpp] view plaincopy
  1. void releasefun()  
  2. {  
  3.     delete singleton::getInstance();  
  4. }  
  5. //在使用完成后调用  
  6. atexit(releasefun);  


3、使用智能指针,比如STL的auto_ptr,于是我们的singleton变成了:

[cpp] view plaincopy
  1. //设计模式之单件模式  
  2. /* 
  3. 作用:保证一个class只有一个实体(instance),并为它提供一个全局唯一的访问点 
  4. */  
  5. #include <memory>  
  6. #include <iostream>  
  7. using namespace std;  
  8. class singleton  
  9. {  
  10. public:  
  11.     ~singleton()  
  12.     {//析构时使用  
  13.     }  
  14.     static singleton* getInstance()  
  15.     {  
  16.         if(NULL == _instance.get())  
  17.         {  
  18.             _instance.reset(new singleton);  
  19.         }  
  20.         return _instance.get();  
  21.     }  
  22. private:  
  23.     static auto_ptr<singleton> _instance;  
  24.   
  25. private:  
  26. //最好将所有此类的实例化的进口全部堵死  
  27.     singleton()  
  28.     {  
  29.   
  30.     }  
  31.     singleton(const singleton&)  
  32.     {  
  33.   
  34.     }  
  35.     singleton& operator=(const singleton &)  
  36.     {  
  37.   
  38.     }  
  39. };  
  40. auto_ptr<singleton> singleton::_instance;  

4、利用c++内嵌类和一个静态成员实现自动释放机制。

[cpp] view plaincopy
  1. //设计模式之单件模式  
  2. /* 
  3. 作用:保证一个class只有一个实体(instance),并为它提供一个全局唯一的访问点 
  4. */  
  5. #include <memory>  
  6. #include <iostream>  
  7. using namespace std;  
  8. class singleton  
  9. {  
  10. public:  
  11.     ~singleton()  
  12.     {//析构时使用  
  13.     }  
  14.     static singleton* getInstance()  
  15.     {  
  16.         if(_instance == NULL)  
  17.         {  
  18.             static clearer clr;  
  19.             _instance = new singleton();  
  20.         }  
  21.         return _instance;  
  22.     }  
  23. private:  
  24.     static singleton *_instance;  
  25. private:  
  26. //最好将所有此类的实例化的进口全部堵死  
  27.     singleton()  
  28.     {  
  29.   
  30.     }  
  31.     singleton(const singleton&)  
  32.     {  
  33.   
  34.     }  
  35.     singleton& operator=(const singleton &)  
  36.     {  
  37.   
  38.     }  
  39.     class clearer  
  40.     {  
  41.     public:  
  42.         clearer(){}  
  43.         ~clearer()  
  44.         {  
  45.             if(singleton::getInstance())  
  46.             {  
  47.                 delete singleton::getInstance();  
  48.             }  
  49.         }  
  50.     };  
  51. };  
  52. singleton *singleton::_instance = NULL;  

针对问题2:多线程版本

引入著名的双检测锁机制

[cpp] view plaincopy
  1. static singleton* getInstance()  
  2. {  
  3.     if(_instance == NULL)  
  4.     {  
  5.         //加入临界区  
  6.         if(NULL == _instance)  
  7.         {  
  8.             _instance = new singleton();  
  9.         }  
  10.         //释放临界区  
  11.     }  
  12.     return _instance;  
  13. }  

于是引入了我们的多线程版本:包含两种释放机制上例提到的3\4方法

[cpp] view plaincopy
  1. //设计模式之单件模式  
  2. /* 
  3. 作用:保证一个class只有一个实体(instance),并为它提供一个全局唯一的访问点 
  4. */  
  5. #include <memory>  
  6. #include <iostream>  
  7. #include <windows.h>  
  8. using namespace std;  
  9.   
  10. class lockguard  
  11. {  
  12. private:  
  13.     CRITICAL_SECTION m_cs;  
  14.   
  15. public:  
  16.     lockguard()  
  17.     {  
  18.         InitializeCriticalSection(&m_cs);  
  19.     }  
  20.     ~lockguard()  
  21.     {  
  22.         DeleteCriticalSection(&m_cs);  
  23.     }  
  24.   
  25. public:  
  26.     class cguard  
  27.     {  
  28.     public:  
  29.         cguard(lockguard &lg)  
  30.             :m_lg(lg)  
  31.         {  
  32.             m_lg.guard();  
  33.         }  
  34.         ~cguard()  
  35.         {  
  36.             m_lg.unguard();  
  37.         }  
  38.     private:  
  39.         lockguard &m_lg;  
  40.     };  
  41. private:  
  42.     void guard()  
  43.     {  
  44.         EnterCriticalSection(&m_cs);  
  45.     }  
  46.     void unguard()  
  47.     {  
  48.         LeaveCriticalSection(&m_cs);  
  49.     }  
  50.     friend class lockguard::cguard;  
  51. };  
  52.   
  53. class singleton  
  54. {  
  55. public:  
  56.     ~singleton()  
  57.     {//析构时使用  
  58.     }  
  59.   
  60. private:  
  61.     static lockguard _lg;  
  62.     static singleton *_instance;  
  63.       
  64.     //static auto_ptr<singleton> _instance;  
  65.   
  66. private:  
  67. //最好将所有此类的实例化的进口全部堵死  
  68.     singleton()  
  69.     {  
  70.   
  71.     }  
  72.     singleton(const singleton&)  
  73.     {  
  74.   
  75.     }  
  76.     singleton& operator=(const singleton &)  
  77.     {  
  78.   
  79.     }  
  80.     class clearer  
  81.     {  
  82.     public:  
  83.         clearer(){}  
  84.         ~clearer()  
  85.         {  
  86.             if(singleton::getInstance())  
  87.             {  
  88.                 delete singleton::getInstance();  
  89.             }  
  90.         }  
  91.     };  
  92. public:  
  93.     static singleton* getInstance()  
  94.     {  
  95.         if(_instance == NULL)  
  96.         {  
  97.             lockguard::cguard gd(_lg);  
  98.             if(NULL == _instance)  
  99.             {  
  100.                 static clearer clr;           
  101.                 _instance = new singleton();  
  102.             }  
  103.         }  
  104.         /*if(NULL == _instance.get()) 
  105.         { 
  106.         _instance.reset(new singleton); 
  107.         }*/  
  108.         return _instance;  
  109.         //return _instance.get();  
  110.     }  
  111. };  
  112. singleton *singleton::_instance = NULL;  
  113. lockguard singleton::_lg;  
  114. //auto_ptr<singleton> singleton::_instance;  

至此我们的singleton模式基本结束了,这个模式还是包含很多c++深层的知识的。

0 0
原创粉丝点击