文档章节

“只生一个娃”--设计模式中的单例模式

青灯夜
 青灯夜
发布于 2015/09/01 22:09
字数 772
阅读 15
收藏 0

“只生一个娃”–设计模式中的单例模式(Singleton)

  • 引言
      被人问到什么是单例模式,突然回答不上来,似乎印象不深了。回去补了一下功课,突然明白了,原来在项目中一直使用的日志模块即采用了单例模式,只是熟视无睹,没有意识到罢了。
      所谓单例模式(Singleton),即指一个类只有一个实例(Instance),并给外界提供访问该实例的一个全局访问点。
      通常我们可以使用全局变量的方式来实现“只生一个娃”,但更好的方法就是:让该类自身负责创建和保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且对外提供一个访问该实例的方法。下面我们看一下具体实现。

  • 单例模式实现
      定义一个Singleton类,添加一个静态方法GetInstance,负责创建自己的唯一实例,并供客户端访问。

class Singleton  
{  
private:  
    Singleton()  
    {  
    }  
    static Singleton *m_pInstance;  

public:  
    static Singleton * GetInstance()  
    {  
        if(m_pInstance == NULL)  //若不存在,则new一个新的实例。 
                m_pInstance = new Singleton();  
        return m_pInstance;  
    }

    //可以定义一个具体干活的方法
    void DoWork()
    {
        printf("the work is done!");   
    }  
}; 

  注意:构造函数设为private,这样外界就不能通过new操作符来实例化该类。
  客户端访问方法:

Singleton* p1 = Singleton :: GetInstance();
Singleton* p2 = p1->GetInstance();
Singleton & ref = * Singleton :: GetInstance();

p1->DoWork();
p2->DoWork();
ref.DoWork();
Singleton :: GetInstance()->DoWork();
  • 问题讨论
    多线程环境下,如果多个线程同时访问Singleton类的GetInstance方法,则有可能造成创建多个实例。因此应该进行加锁保护,可以使用lock机制,确保当一个线程位于代码的临界区时,另一个线程如果访问可被阻塞等待,不进入临界区。可以这样来实现:
class Singleton  
{  
private:  
    Singleton()  
    {  
    }  
    static Singleton *m_pInstance;
    CCriticalSection m_cs;   //定义一个临界区对象
public:  
    static Singleton * GetInstance()  
    {  
        if(NULL == m_pInstance)  //若不存在,则new一个新的实例。 
        {
            lock(m_cs)         //尽在实例未被创建时进行加锁处理
          {
              if(NULL == m_pInstance) //二次判断
              {
                     m_pInstance = new Singleton();  
              }  
          }
        }
        return m_pInstance;  
    }

    //可以定义一个具体干活的方法
    void DoWork()
    {
        printf("the work is done!");   
    }  
}; 

  注意:为什么要二次判断呢?
  第一次NULL == m_pInstance判断是为了避免每次都要加锁,能够提高效率;
  第二次判断是因为:如果实例未被创建,两个线程同时通过第一层NULL == m_pInstance判断,由于lock机制,只有第一个线程进入,另一个排队等候,如果第一个线程创建了实例并出来后,第二个线程进入后还是可以创建新的实例的。

  由此可见:想要保证只生一个小孩真是要时时留意、处处留心,安全措施要绝对保证啊 O(∩_∩)O.

版权声明:本文为csdn博主[applebite](http://blog.csdn.net/applebite) 原创文章,转载请注明出处,侵权必究。 微信添加公众号:qi_chuang 或 猎奇创新平台

© 著作权归作者所有

青灯夜
粉丝 2
博文 35
码字总数 21708
作品 0
朝阳
程序员
私信 提问
设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu
2017/11/02
0
0
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

转载:原地址http://www.cnblogs.com/zhangchenliang/p/3700820.html 简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别 结合简单示例和UML图,讲解工厂模式简单原理。 一、引子 话说...

法斗斗
2018/05/08
277
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
炒冷饭系列:设计模式 抽象工厂模式

炒冷饭系列:设计模式 抽象工厂模式 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 亲爱我,孝何难;亲恶我,孝方贤。 一、什么是抽象工厂模...

泥沙砖瓦浆木匠
2014/07/24
160
0
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用TensorFlow的AI程序运行报错AttributeError: module 'tensorflow' has no attribute 'xxx'

使用TensorFlow的AI程序,在运行时报错AttributeError: module 'tensorflow' has no attribute 'xxx',首先检查是否是包路径不对,一般是版本变化所致。...

织梦之魂
58分钟前
3
0
提示浏览器版本低

本文转载于:专业的前端网站➭提示浏览器版本低 网站网页在遇到浏览器低版本(尤其是IE浏览器)时,提示浏览器版本低(如IE8以及以下),建议用户升级浏览器以获得最好体验。以下是代码: 1...

前端老手
今天
6
0
CentOS 7系统增加swap

转载请注明文章出处:CentOS 7系统增加swap swap是位于磁盘上的特殊文件(或分区),属于“虚拟内存”的一部分。通俗点就是内存的备胎,内存充足的情况下,基本上没swap什么事(和设置有关)...

tlanyan
今天
6
0
基于Prometheus和Grafana的监控平台 - 环境搭建

相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics。 Logging - 用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是我们诊断问题的依据。比如我们说...

JAVA日知录
今天
6
0
PHP运行时全局构造体

struct _php_core_globals { zend_bool magic_quotes_gpc; // 是否对输入的GET/POST/Cookie数据使用自动字符串转义。 zend_bool magic_quotes_runtime; //是否对运行时从外部资源产生的数据使...

冻结not
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部