• 单例模式的c++实现


      1 #pragma once
      2 
      3 #include <iostream>
      4 #include <memory>
      5 #include <Windows.h>
      6 using namespace std;
      7 /***************************************************************************************
      8 
      9 1、首先要有一个创建实例的静态函数GetInstance
     10 2、实现的方式既可以通过new动态创建,也可以通过static静态局部变量实现
     11 3、创建的时机既可以通过静态变量初始化时创建,也可以在调用GetInstance函数时再创建,通过静态变量的初始化的好处是
     12 它是在进入主函数之前创建成功的可以避免多线程的问题,但是坏处就是在程序启动时初始化会拖慢启动过程。
     13 4、为了防止通过调用构造函数创建实例,要将类的构造、复制构造和赋值构造函数设为私有的
     14 5、GetInstance函数的返回值既可以是指针,又可以是引用,当是指针的时候要防止它在中途被delete掉,因此要将析构函数设为私有的
     15 6、这种模式有点像全局变量,但还是有区别的,单件的作用是保证只有一份实例,而能够全局访问是它附带的功能。
     16 
     17 ********************************************************//////////////////////////////////////
     18 class singleton1
     19 {
     20 public:
     21     static singleton1* GetInstance()
     22     {
     23         if(ptr == NULL)
     24             ptr = new singleton1;
     25         return ptr;
     26     }
     27 
     28     static void show()
     29     {
     30         cout << "singleton1::show" << endl;
     31     }
     32 
     33 private:
     34     ~singleton1()
     35     {
     36         cout << "dest singleton1" << endl;
     37     }
     38     static singleton1* ptr;
     39     singleton1()
     40     {
     41         cout << "cstr singleton1" << endl;
     42     }
     43 
     44     singleton1(const singleton1 &);
     45     singleton1& operator=(const singleton1 &);
     46 };
     47 
     48 singleton1* singleton1::ptr = new singleton1;
     49 
     50 /*****************
     51 1、在上面的实现中,使用指针时,不能销毁实例,只有当程序结束时才由系统回收,考虑将指针设计成智能指针shared_ptr,
     52 但是智能指针的回收还是要调用析构函数,声明为public,指针随时会被delete,有很多问题,所以这种方法是不太实用
     53 *****************/
     54 class singleton3
     55 {
     56 public:
     57     ~singleton3()
     58     {
     59         cout << "dest singleton3" << endl;
     60     }
     61 
     62     static singleton3* GetInstance()
     63     {
     64         if(ptr.get() == NULL)
     65             ptr.reset(new singleton3);
     66         return ptr.get();
     67     }
     68 
     69     static void show()
     70     {
     71         cout << "singleton3::show" << endl;
     72     }
     73 
     74 private:
     75     static shared_ptr<singleton3> ptr;
     76     singleton3(){}
     77     singleton3(const singleton3 &);
     78     singleton3& operator=(const singleton3 &);
     79 };
     80 
     81 shared_ptr<singleton3> singleton3::ptr;
     82 
     83 /****************************************
     84 1、上面的实现都是基于new动态创建,并且返回的都是指针类型,这个实现基于静态局部变量,并且返回引用类型
     85 2、返回引用而不是指针的好处是,不用担心中间会被delete掉
     86 3、采用静态局部变量的好处是,内存管理交给系统,不需要手动管理
     87 ****************************************/
     88 class singleton4
     89 {
     90 public:
     91     ~singleton4()
     92     {
     93         cout << "dest singleton4" << endl;
     94     }
     95 
     96     static singleton4& GetInstance()
     97     {
     98         static singleton4 s;
     99         return s;
    100     }
    101 
    102     static void show()
    103     {
    104         cout << "singleton4::show" << endl;
    105     }
    106 
    107 private:
    108     singleton4(){;}
    109     singleton4(const singleton4 &);
    110     singleton4& operator=(const singleton4 &);
    111 };
    112 
    113 /***************************
    114 1、如果是在GetInstance函数中创建实例,并且是多线程的话,如果有多个线程同时调用该函数,
    115 则可能会创建多个实例,所以要对创建过程进行加锁处理
    116 **************************/
    117 CRITICAL_SECTION g_cs;
    118 class Lock
    119 {
    120 public:
    121     Lock()
    122     {
    123         InitializeCriticalSection(&g_cs);
    124     }
    125 
    126     void LockOn()
    127     {
    128         EnterCriticalSection(&g_cs);
    129     }
    130 
    131     void LockOff()
    132     {
    133         LeaveCriticalSection(&g_cs);
    134     }
    135 
    136     ~Lock()
    137     {
    138         DeleteCriticalSection(&g_cs);
    139     }
    140 };
    141 Lock g_lock;
    142 
    143 class singleton5
    144 {
    145 public:
    146     ~singleton5()
    147     {
    148         cout << "dest singleton5" << endl;
    149     }
    150 
    151     static singleton5* GetInstance()
    152     {
    153         if(ptr == NULL)
    154         {
    155             //采用双重判断是为了提高效率,防止每次都要执行加锁过程
    156             g_lock.LockOn();
    157             if(ptr == NULL)
    158                 ptr = new singleton5;
    159             g_lock.LockOff();
    160         }
    161 
    162         return ptr;
    163     }
    164 
    165     static void show()
    166     {
    167         cout << "singleton5::show" << endl;
    168     }
    169 
    170 private:
    171     static singleton5* ptr;
    172     singleton5(){}
    173     singleton5(const singleton5 &);
    174     singleton5& operator=(const singleton5 &);
    175 };
    176 singleton5* singleton5::ptr = NULL;
    177 
    178 /******************
    179 1、上面的实现虽然满足了多线程调用,但是实际中可能会有很多类都要设计成实例模式,
    180 那么就需要都按照上面那样实现一遍,不能重用,下面的模板类就可以满足重用的需求
    181 *******************************/
    182 template <typename T>
    183 class Singleton
    184 {
    185 public:
    186     static T& Instance()
    187     {
    188         if (m_pInstance == NULL)
    189         {
    190             //Lock lock;
    191             g_lock.LockOn();
    192             if (m_pInstance == NULL)
    193             {
    194                 m_pInstance = new T;
    195                 atexit(&Destroy);//将Destroy注册为程序结束时的执行函数释放内存
    196             }
    197 
    198             //return *m_pInstance;
    199             g_lock.LockOff();
    200         }
    201 
    202         return *m_pInstance;
    203     }
    204 
    205 protected:
    206     Singleton(void) 
    207     {
    208         cout << "cstr Singleton" << endl;
    209     }
    210     virtual ~Singleton(void) 
    211     {
    212         cout << "dest Singleton" << endl;
    213     }
    214 
    215 private:
    216     Singleton(const Singleton& rhs)
    217     {
    218         cout << "copy cstr Singleton" << endl;
    219     }
    220     Singleton& operator = (const Singleton& rhs) 
    221     {
    222         cout << "= cstr Singleton" << endl;
    223     }
    224 
    225     static void Destroy()
    226     {
    227         if (m_pInstance != NULL)
    228             delete m_pInstance;
    229         m_pInstance = NULL;
    230     }
    231 
    232     static T* m_pInstance;
    233 };
    234 
    235 template <typename T>
    236 T* Singleton<T>::m_pInstance = NULL;
    237 
    238 //实际的单例类就按照下面的方式实现
    239 class SingletonInstance : public Singleton<SingletonInstance>
    240 {
    241 public:
    242     friend Singleton<SingletonInstance>;
    243     void show()
    244     {
    245         cout << "SingletonInstance::show" << endl;
    246     }
    247 //
    248 private:
    249     SingletonInstance() 
    250     {
    251         cout << "cstr SingletonInstance" << endl;
    252     }
    253     virtual ~SingletonInstance(void) 
    254     {
    255         cout << "dest SingletonInstance" << endl;
    256     }
    257 
    258     SingletonInstance(const SingletonInstance& rhs) 
    259     {
    260         cout << "copy cstr SingletonInstance" << endl;
    261     }
    262 };
    263 
    264 //测试类
    265 class SingletonTest
    266 {
    267 public:
    268     SingletonTest()
    269     {
    270         //singleton1& s1 = singleton1::GetInstance1();
    271         //s1.show();
    272 
    273         //singleton1 *p1 = singleton1::GetInstance();
    274         //p1->show();
    275         ////delete p1;
    276 
    277         //singleton3 *p3 = singleton3::GetInstance();
    278         //p3->show();
    279 
    280         //singleton4 &p4 = singleton4::GetInstance();
    281         //p4.show();
    282 
    283         //singleton5 *p5 = singleton5::GetInstance();
    284         //p5->show();
    285 
    286         SingletonInstance &si = SingletonInstance::Instance();
    287         si.show();
    288     }
    289 };
  • 相关阅读:
    数往知来C#面向对象准备〈二〉
    数往知来C#之面向对象准备〈一〉
    如果我比别人走得更远些,那是因为我站在巨人的肩上。
    小记一下
    关于servlet
    使用session防止表单重复提交
    session和cookie的区别
    数据结构排序算法Java实现
    用背景渐变的透明度设置不同颜色的背景渐变
    Java用DOM方法解析xml
  • 原文地址:https://www.cnblogs.com/suntp/p/6421508.html
Copyright © 2020-2023  润新知