• C++单例模式实例


    定义:在某些情况下,我们设计中的对象只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表对象、日志对象、充当打印机、显卡等设备的驱动程序的对象等。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生。
    这里要说的单件模式就能确保一个类只有一个实例,并提供一个全局访问点。
    在C++中实现如下:
    实现1:
     1 #include <iostream>
     2 using namespace std;
     3  
     4 class CSingleton
     5 {
     6 public:
     7     static CSingleton* getInstance();
     8     static void cleanInstance();
     9     int getValue();
    10     void setValue(int iValue);
    11 private:
    12     int m_iValue;
    13     static CSingleton* m_pSingleton;
    14     CSingleton();
    15     ~CSingleton();
    16 };
    17  
    18 CSingleton* CSingleton::m_pSingleton = NULL;
    19  
    20 CSingleton::CSingleton()
    21 {
    22     cout << "Constructor" << endl;
    23 }
    24  
    25 CSingleton::~CSingleton()
    26 {
    27     cout << "Destructor" << endl;
    28 }
    29  
    30 CSingleton* CSingleton::getInstance()
    31 {
    32     if (NULL == m_pSingleton)
    33     {
    34         m_pSingleton = new CSingleton();
    35     }
    36     return m_pSingleton;
    37 }
    38  
    39 void CSingleton::cleanInstance()
    40 {
    41     delete m_pSingleton; m_pSingleton = NULL;
    42 }
    43  
    44 int CSingleton::getValue()
    45 {
    46     return m_iValue;
    47 }
    48  
    49 void CSingleton::setValue(int iValue)
    50 {
    51     m_iValue = iValue;
    52 }
    53  
    54 int main()
    55 {
    56     CSingleton* pSingleton1 = CSingleton::getInstance();
    57     CSingleton* pSingleton2 = CSingleton::getInstance();
    58     pSingleton1->setValue(123);
    59     if (pSingleton1->getValue() == pSingleton2->getValue())
    60     {
    61         cout << "Two objects is the same instance" << endl;
    62     }
    63     else
    64     {
    65         cout << "Two objects isn't the same instance" << endl;
    66     }
    67  
    68     CSingleton::cleanInstance();
    69     return 0;
    70 }
    相信大多数的同仁都喜欢使用上边这种单件模式的实现方法,如果在单线程的情况下,是没有问题的,但如果是多线程,那么就极有可能会返回两个不同的对象,在调用CSingleton::getInstance的时候,两个线程如果都同时运行完if判断,而又还没有调用到构造函数的话,想象下后果吧。那该怎么办呢?看下边这个实现吧。
    实现2:
     1 #include <iostream>
     2 using namespace std;
     3  
     4 class CSingleton
     5 {
     6 public:
     7     static CSingleton* getInstance();
     8     static void cleanInstance();
     9     int getValue();
    10     void setValue(int iValue);
    11 private:
    12     int m_iValue;
    13     static CSingleton* m_pSingleton;
    14     CSingleton();
    15     ~CSingleton();
    16 };
    17  
    18 // 在进程运行开始就实例化该单件,又称“急切”创建实例
    19 CSingleton* CSingleton::m_pSingleton = new CSingleton();
    20  
    21 CSingleton::CSingleton()
    22 {
    23     cout << "Constructor" << endl;
    24 }
    25  
    26 CSingleton::~CSingleton()
    27 {
    28     cout << "Destructor" << endl;
    29 }
    30  
    31 CSingleton* CSingleton::getInstance()
    32 {
    33     return m_pSingleton;
    34 }
    35  
    36 void CSingleton::cleanInstance()
    37 {
    38     delete m_pSingleton; m_pSingleton = NULL;
    39 }
    40  
    41 int CSingleton::getValue()
    42 {
    43     return m_iValue;
    44 }
    45  
    46 void CSingleton::setValue(int iValue)
    47 {
    48     m_iValue = iValue;
    49 }
    50  
    51 int main()
    52 {
    53     CSingleton* pSingleton1 = CSingleton::getInstance();
    54     CSingleton* pSingleton2 = CSingleton::getInstance();
    55     pSingleton1->setValue(123);
    56     if (pSingleton1->getValue() == pSingleton2->getValue())
    57     {
    58         cout << "Two objects is the same instance" << endl;
    59     }
    60     else
    61     {
    62         cout << "Two objects isn't the same instance" << endl;
    63     }
    64  
    65     CSingleton::cleanInstance();
    66     return 0;
    67 }
    哈哈,看清楚了吗?就是在进程运行的时候就对这个单件进行实例化,可是这样似乎又不能达到延迟实例化的目的啦。如果我们的对象对资源占用非常大,而我们的进行在整个过程中其实并没有用到这个单件,那岂不是白白浪费资源了嘛。还有更好的办法。
    实现3:
     1 #include <iostream>
     2 using namespace std;
     3  
     4 class CSingleton
     5 {
     6 public:
     7     static CSingleton* getInstance();
     8     int getValue();
     9     void setValue(int iValue);
    10 private:
    11     int m_iValue;
    12     CSingleton();
    13     ~CSingleton();
    14 };
    15  
    16 CSingleton::CSingleton()
    17 {
    18     cout << "Constructor" << endl;
    19 }
    20  
    21 CSingleton::~CSingleton()
    22 {
    23     cout << "Destructor" << endl;
    24 }
    25  
    26 CSingleton* CSingleton::getInstance()
    27 {
    28     static CSingleton single;
    29     return &single;
    30 }
    31  
    32 int CSingleton::getValue()
    33 {
    34     return m_iValue;
    35 }
    36  
    37 void CSingleton::setValue(int iValue)
    38 {
    39     m_iValue = iValue;
    40 }
    41  
    42 int main()
    43 {
    44     cout << "Process begin" << endl;
    45     CSingleton* pSingleton1 = CSingleton::getInstance();
    46     CSingleton* pSingleton2 = CSingleton::getInstance();
    47     pSingleton1->setValue(123);
    48     if (pSingleton1->getValue() == pSingleton2->getValue())
    49     {
    50         cout << "Two objects is the same instance" << endl;
    51     }
    52     else
    53     {
    54         cout << "Two objects isn't the same instance" << endl;
    55     }
    56     return 0;
    57 }
    看下运行结果吧:

    Process begin
    Constructor
    Two objects is the same instance
    Destructor

    是不是跟预想的一样呢?把单件声明为成员函数中的静态成员,这样既可以达到延迟实例化的目的,又能达到线程安全的目的,而且看结果的最后,是不是在程序退出的时候,还自动的调用了析构函数呢?这样我们就可以把资源的释放放到析构函数里边,等到程序退出的时候,进程会自动释放这些静态成员的。

  • 相关阅读:
    单张图片转PDF(基于Go语言实现)
    Django在前后端分离项目中,如何针对GET接口请求加入缓存机制
    Python3解决Nginx日志的中文乱码问题
    Python3通过Redis实现学生分数排行榜
    Jmeter之Json提取器用法收藏(非常给力的一篇!)
    H5和安卓的转义字符问题

    数组
    链表
    替换空格 JS算法题
  • 原文地址:https://www.cnblogs.com/berlin-sun/p/CSingleton.html
Copyright © 2020-2023  润新知