单例模式(Singleton)

--本文内容部分引自《大话设计模式 Chapter21》

一.概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  通常我们可以让一个全局变量使一个对象被访问,但它不能阻止你实例化多个对象,一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

二.结构

单例模式因为Singleton类封装它的唯一实例,这样它可以严格的控制客户怎样访问它及何时访问它,简单来说就是对唯一实例的受控访问。

单例类有状态,虽然实例唯一,却可以有子类来继承。

特点:

1、构造函数私有,防止外部实例化。这是第一点要求

2、唯一实例句柄声明为static,这就是所谓唯一

三.单线程模式:

     class CSingleton
{
public:
static CSingleton *GetInstance()
{
if (NULL != m_Instance)
{
m_Instace = new CSingleton();
}
} private:
CSingleton(); private:
static CSingleton * m_Instance;
};
//此处初始化
CSingleton* CSingleton::m_Instace = NULL;

这里相应有一些可以提升的地方,比如实际实例类型不定的情况下,这里可以改为使用模板,类型待编译时刻再定;仅仅私有构造,还有其他方式会导致实例化,如拷贝构造。

     template <typename T>
class CSingleton
{
public:
static T *GetInstance()
{
if (NULL != m_Instance)
{
m_Instace = new T;
}
} private:
CSingleton();
CSingleton(const T&);
void operator=(const T&); private:
static T * m_Instance;
}; //此处初始化
template <typename T>
T* CSingleton<T>::m_m_Instance= NULL;

四、多线程模式:

首先,提到多线程,那就马上要考虑同步的问题了,说到底就是锁,具体锁怎么实现这里不赘叙。

         static T *GetInstance()
{
m_mutex.Lock();
if (NULL != m_Instance)
{
m_Instance = new T;
}
m_mutex.UnLock();
}

还有需要考虑一个会遇到的多线程情况下遇到的问题,那就是上面写法的锁的位置,当句柄为NULL时,同时有两个线程调用到了GetInstance入口,拿到时间片的线程进入if里面new出对象,结束后另一个线程进入后,依旧会再new一次。这种可能是存在的。

为了应对这种低概率但又不能无视的情况,大神们给出了方案--双重锁定(Double-Check Locking).

GetInstance函数修改如下:

         static T *GetInstance()
{
if (NULL != m_Instance)
{
m_mutex.Lock();
if (NULL != m_Instance)
{
m_Instance = new T;
}
m_mutex.UnLock();
}
}

五、总结

1.以上所有代码实现都是所谓的懒汉式单例类,因为是在第一次被引用时才会将自己实例化。

相对有饿汉模式,就是在以上代码初始化的地方直接写成

     template <typename T>
T* CSingleton::m_Instance = new T;

这种静态初始化的方式称为饿汉式单例类

2.目前实际使用中,只在项目工程中的日志记录、配置文件操作、内存池等全局唯一实例上,使用起来还是很方便的。

单例模式-C++的更多相关文章

  1. C++实现线程安全的单例模式

    在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...

  2. 23种设计模式--单例模式-Singleton

    一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...

  3. angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用

    今天我们要讲的是ng2的路由系统. 例子

  4. java设计模式之--单例模式

    前言:最近看完<java多线程编程核心技术>一书后,对第六章的单例模式和多线程这章颇有兴趣,我知道我看完书还是记不住多少的,写篇博客记录自己所学的只是还是很有必要的,学习贵在坚持. 单例模 ...

  5. 设计模式C#合集--单例模式

    单例模式 代码: 第一种: private static Singleton singleton = null; private Singleton() { } public static Singl ...

  6. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

  7. GOF23设计模式之单例模式

    ·核心作用: -保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. ·常见应用场景: -Windows的Task Manager(任务管理器)就是很典型的单例模式 -Windows的Recy ...

  8. GJM : C#设计模式(1)——单例模式

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  9. PHP设计模式(四)单例模式(Singleton For PHP)

    今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...

  10. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

随机推荐

  1. Unity 3D 我来了

  2. github安装&初探

    主要记录安装中的问题: 1 centos 5和6的epel源需要不同的包来更新 Centos 5.x wget http://dl.fedoraproject.org/pub/epel/5/x86_6 ...

  3. JAVA SSM 示例代码

    SSM 即spring+spring mvc+mybatis,开发工具IDEA 1.先看下项目结构如图: 2.主要配置文件 spring-mvc.xml <?xml version=" ...

  4. JS 中没有按地址(引用)传递,只有按值传递

    很多人,包括我,受书本知识消化不彻底的影响,认为 JS 中参数有两种传递方式:数字.字符串等按值传递:数组.对象等按地址(引用)传递.对此种观点,我们要谨慎. var v1 = [] var v2 = ...

  5. iOS开发的小技巧

    转自简书:http://www.jianshu.com/p/50b63a221f09  http://www.jianshu.com/p/08f194e9904c 原作者:叶孤城___ self.ta ...

  6. Lex使用指南

    Lex是由美国Bell实验室M.Lesk等人用C语言开发的一种词法分析器自动生成工具,它提供一种供开发者编写词法规则(正规式等)的语言(Lex语言)以及这种语言的翻译器(这种翻译器将Lex语言编写的规 ...

  7. HTML5本地存储——Web SQL Database

    在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数据就 ...

  8. JavaScript中两个感叹号的作用

    先用一个简单的例子说明:var o={flag:true};var test=!!o.flag;//等效于var test=o.flag||false;alert(test);由于对null与unde ...

  9. HDU 3642 Get The Treasury (线段树扫描线)

    题意:给你一些长方体,问你覆盖三次及以上的体积有多大 首先我们观察x轴y轴一样很大,但是z轴很小,所以我们可以枚举z轴(-500,500),注意我们枚举的是每一段长度为一的z轴的xy轴的面积而不是点. ...

  10. javascript数组去重的两个方法

    方法一: 创建一个临时数组,判断目标数组中每个元素是否在临时数组中,如果不在就添加进临时数组,最后return临时数组 <script> var arr=[1,2,3,4,5,1,2,3, ...