单例模式(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.目前实际使用中,只在项目工程中的日志记录、配置文件操作、内存池等全局唯一实例上,使用起来还是很方便的。

最新文章

  1. SQL总结(四)编辑类
  2. JdbcTemplate主要提供以下五类方法:
  3. connect to tomcat with JMX
  4. ACM之数学题
  5. Linux内核学习笔记
  6. 通过程序 VB.Net 或 C# 读取文本文件行数
  7. win7 开wifi热点
  8. boost------function的使用(Boost程序库完全开发指南)读书笔记
  9. [Swift]LeetCode726. 原子的数量 | Number of Atoms
  10. [一]class 文件浅析 .class文件格式详解 字段方法属性常量池字段 class文件属性表 数据类型 数据结构
  11. Ex0203
  12. 转:vue项目如何刷新当前页面
  13. Mac 永久添加 环境变量方法
  14. Make ProgressBar Vertical
  15. HDU 5607 graph(矩阵乘法)
  16. HTML Tags
  17. 于erlang依赖的linux调优
  18. svn的下载链接
  19. sublime text配置make工具
  20. 103-advanced-上下文

热门文章

  1. Javascript 执行环境及作用域
  2. ios 抓取真机的网络包
  3. [转] ImageView的android:adjustViewBounds属性
  4. Rest(表述性状态转移)
  5. Core Data使用
  6. WPF播放视频
  7. CozyRSS开发记录3-标题栏再加强
  8. 转载--PayPal高级工程总监:读完这100篇论文 就能成大数据高手
  9. WPF下的仿QQ图片查看器
  10. 首师大附中互测题:LJX的校园:入学典礼【C003】