单例模式是什么??

单例模式(Singleton)是一种常用的设计模式,它能够保证系统中应用该模式的类只有一个实例。


为什么要存在单例模式??

在很多场景下,我们都希望一个类只能创建出唯一的对象,例如windows下的任务管理器,我们就只能打开一个。若不使用单例模式,就会在多次打开时弹出多个窗口,重复对象,浪费内存。而且要是多个窗口的状态不一致,也会造成误解。因此保证某个对象只能有一个实例这一点很重要。


单例模式的特点:

1.一个类只能有一个实例
2.该类必须自己创建该实例
3.必须向整个系统提供该实例

对应它的三个特点,我们需要做的是:

  • 构造函数声明为私有的
  • 该类中要包含该类的静态私有对象
  • 提供一个共有的静态成员函数来创建或获取它本身的私有对象

两种实现方式(饿汉模式&&懒汉模式)


饿汉模式

  • 利用静态成员变量初始化在调main函数之前的特性实现,对象定义后,数据立即加载到内存。
  • 以空间换取时间

  • 这种方式没有加锁,没有双重检查,也不用考虑异常捕获造成的内存泄漏。

//------------------------hangry_pattern-------------------------------------
//通过类模板来实现
template<class T>
class Singleton_hangry
{public://该函数用来获取唯一实例static T* GetInstance(){assert(_inst);return _inst;}protected://构造函数定义为保护的,在其派生类中也可见Singleton_hangry(){};private://由于静态成员函数不能调用非静态的成员变量,所以声明成静态的类对象指针static T* _inst;//拷贝构造和运算符重载函数定义为私有,目的是防拷贝Singleton_hangry(const T &);Singleton_hangry& operator=(const T&);
};//静态成员变量要在类外进行初始化
//初始化时创建唯一实例,在main函数调用前就会执行
//空间换时间的做法
template<class T>
T* Singleton_hangry<T>::_inst=new T;

测试代码:

//-------------------TestCode----------------------------------------------------
int main()
{int* p1=Singleton_hangry<int>::GetInstance();int* p2=Singleton_hangry<int>::GetInstance();cout<<"p1==>"<<p1<<endl;cout<<"p2==>"<<p2<<endl;return 0;
}

执行结果:

p1==>0x10cec20
p2==>0x10cec20

懒汉模式

这种模式是在执行时,首次调用获取唯一实例的接口函数时才会加载内存,延时加载。

//---------------------------lazy_pattern------------------
template<class T>
class Singleton_lazy
{public://创建或获取唯一实例static T* GetInstance(){if(_inst==NULL)_inst=new T;return _inst;}protected://构造函数定义成保护为了在继承时派生类可见Singleton_lazy(){};private://唯一实例static T* _inst;//防拷贝Singleton_lazy(const T&);T& operator=(const T&);
};//main函数执行前先将该实例初始化为空,运行时再加载
template<class T>
T* Singleton_lazy<T>::_inst=NULL;

测试代码:

//-----------------------------TestCode------------------------
int main()
{char* p1=Singleton_lazy<char>::GetInstance();char* p2=Singleton_lazy<char>::GetInstance();cout<<"p1----->"<<(void*)p1<<endl;cout<<"p2----->"<<(void*)p2<<endl;return 0;
}

执行结果:

p1----->0x16bbc20
p2----->0x16bbc20

这样的实现方式其实是线程不安全的,因为在判断_inst是否为空,以及使用new申请空间这两步不是原子操作,在中间可能有其他线程进来,导致创建出来两个实例,不符合我们的期望。基于此,要让它成为线程安全函数就需要对其进行加锁

static T* GetInstance(){pthread_mutex_lock(&lock);if(_inst==NULL){_inst=new T;}pthread_mutex_unlock(&lock);return _inst}

在每一次对_inst进行判空时都要上锁,这样的加锁方式使性能大大下降,显然不满足单例模式高效的特点。因此,对其进行优化,采用双重检查的方式实现。

完整代码:

#include <iostream>
#include <pthread.h>
using namespace std;//--------------------lazy_safe_pattern------------------
template<class T>
class Singleton_lazy
{public://初始化互斥锁static pthread_mutex_t lock;static T* GetInstance(){if(_inst==NULL){pthread_mutex_lock(&lock);if(_inst==NULL){_inst=new T;}pthread_mutex_unlock(&lock);}return _inst;}protected://构造函数定义成保护为了在继承时派生类可见Singleton_lazy(){};private://唯一实例static T* _inst;//防拷贝Singleton_lazy(const T&);T& operator=(const T&);
};//main函数执行前先将该实例初始化为空,运行时再加载
template<class T>
T* Singleton_lazy<T>::_inst=NULL;
template<class T>
pthread_mutex_t Singleton_lazy<T>::lock;//-----------------------------TestCode------------------------
int main()
{char* p1=Singleton_lazy<char>::GetInstance();char* p2=Singleton_lazy<char>::GetInstance();cout<<"p1----->"<<(void*)p1<<endl;cout<<"p2----->"<<(void*)p2<<endl;return 0;
}

测试结果:

p1----->0x10cbc20
p2----->0x10cbc20

单例模式——C++版相关推荐

  1. 23种设计模式(一)单例模式

    2019独角兽企业重金招聘Python工程师标准>>> 定义 单例模式最初的定义出现于<设计模式>(艾迪生维斯理, 1994):"保证一个类仅有一个实例,并提供 ...

  2. 【Python】《大话设计模式》Python版代码实现

    <大话设计模式>Python版代码实现 上一周把<大话设计模式>看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多.偶尔会用到一些脚本语言写脚本的人来说,很是开阔眼 ...

  3. Python 单例模式

    #单例模式 class Dog(object):#定义一个类变量#None相当于c++中的NULL,修饰基本类型和类类型均可instance = None#重写__new__方法def __new__ ...

  4. 《大话设计模式》Python 版代码实现

    From:http://www.cnblogs.com/wuyuegb2312/archive/2013/04/09/3008320.html 一.简单工厂模式 模式特点:工厂根据条件产生不同功能的类 ...

  5. 【设计模式】5、单例模式

    原始单例模式 1 package com.shejimoshi.create.Singleton; 2 3 4 /** 5 * 功能:保证一个类仅有一个实例,并提供一个访问它的全局访问点 6 * 适用 ...

  6. 《大话设计模式》Python版代码实现

    <大话设计模式>Python版代码实现 上一周把<大话设计模式>看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多.偶尔会用到一些脚本语言写脚本的人来说,很是开阔眼 ...

  7. 漫画:什么是单例设计模式

    转载自 永远爱大家的 程序员小灰 -----  第二天  ----- 单例模式第一版: 1 2 3 4 5 6 7 8 9 10 11 public class Singleton {     pri ...

  8. Java笔试面试-设计模式

    1.说一下设计模式?你都知道哪些? 答:设计模式总共有 23 种,总体来说可以分为三大类:创建型模式( Creational Patterns ).结构型模式( Structural Patterns ...

  9. java面试题大合集

    文章目录 单例模式 最简单的第一版 单例模式第二版:(线程安全) 第三版: (补充线程安全) HashMap hashmap 1.7 hashmap 1.8 锁升级的过程 扩容机制 HashMap的H ...

最新文章

  1. 讨论:写程序到底需不需要懂数学?
  2. Error:No resource identifier found for attribute 'appComponentFactory' in packag
  3. 【案例】常驻查询引发的thread pool 性能问题之二
  4. java中android_在Android中用纯Java代码布局
  5. 使用MVC框架中要注意的问题(二):将Model和Controller单独用一个项目设计
  6. css里slidebottom,jquery - 从CSS“top”到“bottom”的jQuery动画 - 堆栈内存溢出
  7. java面试题整理_2018年最新java面试题整理。。。持续更新中。。。
  8. 2008服务器系统来电自启,服务器2008自动重启
  9. 求助,关于MFC中的 Secur32.lib问题
  10. 华硕n54u mysql_改华硕[N14U N54U]5G 2G的7620老毛子Padavan固件(私人云储存 ari
  11. 使用 ESP-Prog / Jlink 进行 JTAG 调试时的常见错误及解决办法
  12. 【大话设计模式-11】组合模式(案例解析)
  13. IT行业为何如此吃香?2019学习IT就业前景分析
  14. 漫画:什么是IaaS、PaaS、SaaS?
  15. 机器学习笔记(3.1)
  16. Oracle分区表及分区索引
  17. 五分钟学会用Simulink模型生成HDL代码
  18. Python编程:函数
  19. CAN通讯车用触摸显示器
  20. 查看oracle版本及补丁,检查及升级Oracle数据库补丁版本

热门文章

  1. Ubutnu18.04解决:Starting Wait until snapd is fully seeded...
  2. 创业初期,教你迅速组建优秀的创业团队
  3. MySQL数据库(5)
  4. JDK版本不兼容问题
  5. SQL学习-2.7 SQL聚合
  6. 在应用程序中将OJB作为一个存储层使用(六) (转)
  7. 精确拐点交易体系之追涨停策略
  8. CentOS进入紧急模式怎么解决
  9. ajax的常用api测试
  10. 酵母中微量元素螯合物的饲料添加剂及其生产方法