• C++完美实现Singleton模式


    Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却也不是件容易的事情。
    标准的实现
     
    1 class Singleton
     2 {
     3 public:
     4        static Singleton * Instance()
     5        {
     6               if( 0== _instance)
     7               {
     8                      _instance = new Singleton;
     9               }
    10               return _instance;
    11        }
    12 protected:
    13        Singleton(void)
    14        {
    15        }
    16        virtual ~Singleton(void)
    17        {
    18        }
    19        static Singleton* _instance;
    20 };
    

      

    这是教科书上使用的方法。看起来没有什么问题,其实包含很多的问题。下面我们一个一个的解决。
    问题一  自动垃圾回收
    上面的程序必须记住在程序结束的时候,释放内存。为了让它自动的释放内存,我们引入auto_ptr改变它。
     
    1 #include <memory>
     2 #include <iostream>
     3 using namespace std;
     4 class Singleton
     5 {
     6 public:
     7        static Singleton * Instance()
     8        {
     9               if( 0== _instance.get())
    10               {
    11                      _instance.reset( new Singleton);
    12               }
    13               return _instance.get();
    14        }
    15 protected:
    16        Singleton(void)
    17        {
    18               cout <<"Create Singleton"<<endl;
    19        }
    20        virtual ~Singleton(void)
    21        {
    22               cout << "Destroy Singleton"<<endl;
    23        }
    24        friend class auto_ptr<Singleton>;
    25        static auto_ptr<Singleton> _instance;
    26 };
    27 //Singleton.cpp
    28 auto_ptr<Singleton> Singleton::_instance;
    

      

    问题二  增加模板
    在我的一个工程中,有多个的Singleton类,对Singleton类,我都要实现上面这一切,这让我觉得烦死了。于是我想到了模板来完成这些重
    复的工作。
    现在我们要添加本文中最吸引人单件实现:
     
    1 #include <memory>
     2 using namespace std;
     3 using namespace C2217::Win32;
     4  
     5 namespace C2217
     6 {
     7 namespace Pattern
     8 {
     9 template <class T>
    10 class Singleton
    11 {
    12 public:
    13        static inline T* instance();
    14       
    15 private:
    16        Singleton(void){}
    17        ~Singleton(void){}
    18        Singleton(const Singleton&){}
    19        Singleton & operator= (const Singleton &){}
    20  
    21        static auto_ptr<T> _instance;
    22 };
    23  
    24 template <class T>
    25 auto_ptr<T> Singleton<T>::_instance;
    26  
    27 template <class T>
    28  inline T* Singleton<T>::instance()
    29 {
    30        if( 0== _instance.get())
    31        {
    32               _instance.reset ( new T);
    33        }
    34       
    35        return _instance.get();
    36 }
    37  
    38 //Class that will implement the singleton mode,
    39 //must use the macro in it's delare file
    40 #define DECLARE_SINGLETON_CLASS( type ) \
    41        friend class auto_ptr< type >;\
    42        friend class Singleton< type >;
    43 }
    44 }
    

      

    问题三  线程安全
    上面的程序可以适应单线程的程序。但是如果把它用到多线程的程序就会发生问题。主要的问题在于同时执行_instance.reset ( new T); 
    就会同时产生两个新的对象,然后马上释放一个,这跟Singleton模式的本意不符。所以,你需要更加安全的版本:
     
    1 #include <memory>
     2 using namespace std;
     3 #include "Interlocked.h"
     4 using namespace C2217::Win32;
     5  
     6 namespace C2217
     7 {
     8 namespace Pattern
     9 {
    10 template <class T>
    11 class Singleton
    12 {
    13 public:
    14        static inline T* instance();
    15       
    16 private:
    17        Singleton(void){}
    18        ~Singleton(void){}
    19        Singleton(const Singleton&){}
    20        Singleton & operator= (const Singleton &){}
    21  
    22        static auto_ptr<T> _instance;
    23        static CResGuard _rs;
    24 };
    25  
    26 template <class T>
    27 auto_ptr<T> Singleton<T>::_instance;
    28  
    29 template <class T>
    30 CResGuard Singleton<T>::_rs;
    31  
    32 template <class T>
    33  inline T* Singleton<T>::instance()
    34 {
    35        if( 0 == _instance.get() )
    36        {
    37               CResGuard::CGuard gd(_rs);
    38               if( 0== _instance.get())
    39               {
    40                      _instance.reset ( new T);
    41               }
    42        }
    43        return _instance.get();
    44 }
    45  
    46 //Class that will implement the singleton mode,
    47 //must use the macro in it's delare file
    48 #define DECLARE_SINGLETON_CLASS( type ) \
    49        friend class auto_ptr< type >;\
    50        friend class Singleton< type >;
    51 }
    52 }
    CresGuard 类主要的功能是线程访问同步,代码如下:
     1 class CResGuard {
     2 public:
     3    CResGuard()  { m_lGrdCnt = 0; InitializeCriticalSection(&m_cs); }
     4    ~CResGuard() { DeleteCriticalSection(&m_cs); }
     5  
     6    // IsGuarded is used for debugging
     7    BOOL IsGuarded() const { return(m_lGrdCnt > 0); }
     8  
     9 public:
    10    class CGuard {
    11    public:
    12       CGuard(CResGuard& rg) : m_rg(rg) { m_rg.Guard(); };
    13       ~CGuard() { m_rg.Unguard(); }
    14  
    15    private:
    16       CResGuard& m_rg;
    17    };
    18  
    19 private:
    20    void Guard()   { EnterCriticalSection(&m_cs); m_lGrdCnt++; }
    21    void Unguard() { m_lGrdCnt--; LeaveCriticalSection(&m_cs); }
    22  
    23    // Guard/Unguard can only be accessed by the nested CGuard class.
    24    friend class CResGuard::CGuard;
    25  
    26 private:
    27    CRITICAL_SECTION m_cs;
    28    long m_lGrdCnt;   // # of EnterCriticalSection calls
    29 };
    

      

    问题四  实用方法

    比如你有一个需要实现单件模式的类,就应该这样实现:
     
    1 #include "singleton.h"
     2 using namespace C2217::Pattern;
     3  
     4 class ServiceManger
     5 {
     6 public:
     7        void Run()
     8        {
     9        }
    10 private:
    11        ServiceManger(void)
    12        {
    13        }
    14        virtual ~ServiceManger(void)
    15        {
    16        }
    17        DECLARE_SINGLETON_CLASS(ServiceManger);
    18 };
    19  
    20 typedef Singleton<ServiceManger> SSManger;
    

      

    在使用的时候很简单,跟一般的Singleton实现的方法没有什么不同。
    1 int _tmain(int argc, _TCHAR* argv[])
    2 {
    3         SSManger::instance()->Run();
    4 }
    

      

    一个简单的Singleton模式的实现,可以看到C++语言背后隐藏的丰富的语意,我希望有人能实现一个更好的Singleton让大家学习。
  • 相关阅读:
    又回来咯
    4 20210412-1 原型设计作业
    3 20210405-1 案例分析作业
    202103226-1 编程作业
    阅读任务
    准备工作
    原型设计作业
    案例分析
    编程作业
    构建之法读后感
  • 原文地址:https://www.cnblogs.com/ligun123/p/2770386.html
Copyright © 2020-2023  润新知