一.概念

单例模式:其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

  1. class CSingleton
  2. {
  3. //公有的静态方法,来获取该实例
  4. public:
  5. static CSingleton* GetInstance()
  6. {
  7. if ( m_pInstance == NULL )  //判断是否第一次调用
  8. m_pInstance = new CSingleton();
  9. return m_pInstance;
  10. }
  11. //私有构造函数,防止实例化
  12. private:
  13. CSingleton(){};
  14. //私有静态指针变量,指向类的唯一实例
  15. private:
  16. static CSingleton * m_pInstance; //声明一个静态成员
  17. };
  18. CSingleton* CSingleton::m_pInstance = NULL; //定义并初始化静态数据成员
  19. int main()
  20. {
  21. CSingleton* ps1 = CSingleton::GetInstance();
  22. CSingleton* ps2 = CSingleton::GetInstance();
  23. CSingleton* ps3 = ps1->GetInstance();
  24. CSingleton & ps4 = * CSingleton :: GetInstance();
  25. if (ps1 == ps2)
  26. {
  27. cout<< "ps1 = ps2"<<endl;
  28. }
  29. if (ps1 == ps3)
  30. {
  31. cout<< "ps1 = ps3"<<endl;
  32. }
  33. if (&ps4 == ps1)
  34. {
  35. cout<< "ps1 = ps4"<<endl;
  36. }
  37. return 0;
  38. }

单例模式通过类本身来管理其唯一实例,唯一的实例是类的一个普通对象,但设计这个类时,让它只能创建一个实例并提供对此实例的全局访问。

用户访问唯一实例的方法只有
GetInstance() 成员函数。如果不通过这个函数,任何创建实例的尝试都将失败,因为类的构造函数是私有的。

有一点要注意:一定要加上
CSingleton* CSingleton::m_pInstance = NULL; 这一句,不然的话编译会出错,因为这一句才是变量定义。

二.单例类CSingleton 有以下特征

它有一个指向唯一实例的静态指针m_pInstance,并且是私有的;

它有一个公有的函数,可以获取这个唯一的实例,并且在需要的时候创建该实例;

它的构造函数是私有的,这样就不能从别处创建该类的实例。

三.存在的问题

1.m_pInstance
指向的空间什么时候释放呢?

如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面的代码无法实现这个要求。我们需要一种方法,正常的删除该实例。

不合理的解决方法:

在程序结束时调用
GetInstance(),并对返回的指针掉用 delete操作。这样做可以实现功能,但不仅很丑陋,而且容易出错。因为这样的附加代码很容易被忘记,而且也很难保证在delete之后,没有代码再调用
GetInstance 函数。也就是说释放操作由使用者来管理,而不是由类本身来管理,这违背了类的单一职责的原则,这是不合理的。

2. 该实例的析构函数什么时候执行?

上面的类里为什么没有析构函数,其实即便你加上析构函数也是可以的,但是这个析构函数不会被执行的。因为你的实例是 new 出来的,所以只有 delete 时,才会调用析构函数,但是在哪里调用 delete 呢!?这又回到了上面的问题。

一种妥善的方法:

  1. class CSingleton
  2. {
  3. public:
  4. static CSingleton* GetInstance()
  5. {
  6. static CSingleton instance; //静态局部变量
  7. return &instance;
  8. }
  9. private:
  10. CSingleton() {}; //构造函数
  11. };

局部静态对象实例 instance 是第一次调用 GetInstance() 时被构造,一直保持活动状态直到应用程序终止,与动态分配对象不同,静态对象当应用程序终止时被自动销毁掉,所以就不必再手动销毁实例了。

当然这里,可以加上析构函数来处理你想要的操作。

这样做的要点有以下几点:

1. 静态变量在内存中只有一份,从而保证了单例模式中单一实例的要求。

2. 静态变量在程序终止时会被自动销毁,从而保证了空间正常释放。

设计模式C++描述----01.单例(Singleton)模式的更多相关文章

  1. JavaScript 设计模式之----单体(单例)模式

    设计模式之--单体(单例)模式 1.介绍 从本章开始,我们会逐步介绍在JavaScript里使用的各种设计模式实现,在这里我不会过多地介绍模式本身的理论,而只会关注实现.OK,正式开始. 在传统开发工 ...

  2. 漫谈设计模式(二):单例(Singleton)模式

    1.前言 实际业务中,大多业务类只需要一个对象就能完成所有工作,另外再创建其他对象就显得浪费内存空间了,例如web开发中的servlet,这时便要用到单例模式,就如其名一样,此模式使某个类只能生成唯一 ...

  3. ① 设计模式的艺术-01.单例(Singleton)模式

    单例模式为何要出现 在工作过程中,发现所有可以使用单例模式的类都有一个共性,那就是这个类没有自己的状态,换句话说,这些类无论你实例化多少个,其实都是一样的. 如果我们不将这个类控制成单例的结构,应用中 ...

  4. Android与设计模式——单例(Singleton)模式

    概念: java中单例模式是一种常见的设计模式.单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类仅仅能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  5. JAVA中实现单例(Singleton)模式的八种方式

    单例模式 单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例. 基本的实现思路 单 ...

  6. 【Java学习笔记之三十】详解Java单例(Singleton)模式

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

  7. 设计一个线程安全的单例(Singleton)模式

    在设计单例模式的时候.尽管非常easy设计出符合单例模式原则的类类型,可是考虑到垃圾回收机制以及线程安全性.须要我们思考的很多其它.有些设计尽管能够勉强满足项目要求,可是在进行多线程设计的时候.不考虑 ...

  8. 单例Singleton模式的两种实现方法

    在设计模式中,有一种叫Singleton模式的,用它可以实现一次只运行一个实例.就是说在程序运行期间,某个类只能有一个实例在运行.这种模式用途比较广泛,会经常用到,下面是Singleton模式的两种实 ...

  9. Java设计模式透析之 —— 单例(Singleton)

    写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至像f ...

随机推荐

  1. 使用ImageIO.write上传二维码文件时候,提示系统找不到指定路径

    报错如图所示: java.io.FileNotFoundException: E:\SF\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtp ...

  2. Spring IOC(1)----容器刷新(refresh())之前

    首先本次分析是基于注解形式的,想来xml格式的原理都是类似的. 首先说一下什么是Bean定义(beandefinition):bean定义并不是实例化的bean,而是bean对象的一些信息,根据这些定 ...

  3. jobs后台任务

    前台作业:占据了命令提示符,就是你当前可以操作的作业后台作业:启动之后,释放命令提示符,后续的操作在后台完成 前台——>后台 ctrl+z:把正在前台的作业送往后台,这时作业的状态是暂停. CO ...

  4. Hbase入门(四)——表结构设计-RowKey

    Hbase的表结构设计与关系型数据库有很多不同,主要是Hbase有Rowkey和列族.timestamp这几个全新的概念,如何设计表结构就非常的重要. 创建 Hbase就是通过 表 Rowkey 列族 ...

  5. 【每天一题】LeetCode 0020. 有效的括号

    开源地址:https://github.com/jiauzhang/algorithms 题目 /* * https://leetcode-cn.com/problems/valid-parenthe ...

  6. IDEA 学习笔记之 1.5已经过时问题

    1.5已经过时问题: apache-maven-3.5.0\conf\settings.xml添加: <profile> <id>jdk-1.8</id> < ...

  7. Vim升华之树形目录插件NERDTree安装图解(ubuntu)

    此文经验证:为真 http://www.linuxidc.com/Linux/2013-06/86048.htm

  8. Nginx简单介绍以及linux下使用Nginx进行负载均衡的搭建

    1.Nginx简介 Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支支撑5 ...

  9. django的url分发封装

    h2, body>h3, body>h4, body>h1{ padding: 10px; background-color: #4cae4c; text-align: center ...

  10. Mr. Rito Post Office

    あなたは離島の郵便局に勤めるプログラマである.あなたの住んでいる地域は,複数の島々からなる.各島には一つ以上の港町がある.それらに加えて他の町や村があるかもしない.ある島から別の島に向かうためには船を ...