1、什么是单例模式

  在架构设计时,某些类在整个系统生命周期中最多只能有一个对象存在 ( Single Instance )。如超市收银系统,其外观主要由显示器(1个)、扫描枪(1个)、收款箱(1个)组成,在系统正常运行期间这三部分都是唯一存在的;也就是说,显示器、扫描枪、收款箱这三部分都应该有各自的类,并且每个类只能唯一地实例化一个对象,基于这种模式的程序设计,称为单例模式。

  !!!单例模式只能创建一个对象,且该对象的生命周期伴随系统的整个运行期间。

2、怎么实现单例模式

  思考:如何定义一个类,使得这个类最多只能创建一个对象?

  分析:因为对象是由构造函数创建的,所以我们应该将问题锁定在构造函数上;又因为只能创建一个对象,这就意味着只能调用一次构造函数;显然将构造函数的访问权限设置为 public 不合适,所以,构造函数的访问权限只能是 private。然后,定义一个私有的静态成员 c_instance = NULL 和 公有的静态成员函数,通过  c_instance 来判断是否创建对象。(这个为什么要使用 静态成员呢?因为构造函数是私有的,在类的外部无法创建对象,只能通过类名调用静态成员,而静态成员函数只能调用静态成员变量)

  上述分析过程可简化为:

  (1)将构造函数的访问属性设置为 private;

  (2)定义私有的静态成员属性 instance 并初始化为 NULL;

  (3)当需要使用对象时,访问 instance 的值;

1)空值:创建对象,并用 instance 标记;

2)非空值:返回 instance 标记的对象;

 #include <iostream>
#include <string> using namespace std; class SObject
{
static SObject* c_instance; // 定义标识符指针; /* 不需用拷贝和赋值,在单例模式中,始终只有一个对象 */
SObject(const SObject&);
SObject& operator= (const SObject&); SObject() // 私有的构造函数
{
}
public:
static SObject* GetInstance(); // 创建对象的入口 void print()
{
cout << "this = " << this << endl;
}
}; SObject* SObject::c_instance = NULL; // 静态成员类内声明,类外定义 SObject* SObject::GetInstance() // 单例模式的关键
{
if( c_instance == NULL )
{
c_instance = new SObject();
} return c_instance;
} int main()
{
SObject* s = SObject::GetInstance();
SObject* s1 = SObject::GetInstance();
SObject* s2 = SObject::GetInstance(); s->print(); // this = 0x940a008
s1->print(); // this = 0x940a008
s2->print(); // this = 0x940a008 return ;
}
// 注:单例模式中,对象的生命周期存在整个系统运行过程中,所以是绝对不释放的;

单例模式实现

·   其实,在上述的单例模式实现案列中,有一部分代码(分析过程中第2、3步)与类本身没有任何关系,既然是这样,我们就把这部分单独提取出来处理。

  问题所在:需要使用单例模式时,必须在每个类中定义 静态成员变量 c_instance 和 静态成员函数 GetInstance();当有多个类都需要使用单例模式时,这样的实现方式明显的很冗余,为了能够代码复用,我们可以 将这两部分抽象成一个新类(做成类模板,声明为其它类的友元类,这样与之前的效果一样)。

 // 对上个单例模式实现代码的改进

 // singleton.hpp 单例模式代码
#ifndef SINGLETON_H
#define SINGLETON_H template
< typename T >
class Singleton
{
static T* c_instance;
public:
static T* GetInstance();
}; template
< typename T >
T* Singleton<T>::c_instance = NULL; template
< typename T >
T* Singleton<T>::GetInstance()
{
if( c_instance == NULL )
{
c_instance = new T();
} return c_instance;
} #endif // main.cpp 测试文件
#include <iostream>
#include <string>
#include "singleton.hpp" using namespace std; class SObject
{
friend class Singleton<SObject>; // 当前类需要使用单例模式 SObject(const SObject&);
SObject& operator= (const SObject&); SObject()
{
}
public: void print()
{
cout << "this = " << this << endl;
}
}; int main()
{
SObject* s = Singleton<SObject>::GetInstance();
SObject* s1 = Singleton<SObject>::GetInstance();
SObject* s2 = Singleton<SObject>::GetInstance(); s->print(); // 0xe63c20
s1->print(); // 0xe63c20
s2->print(); // 0xe63c20 return ;
}

基于类模板的单例模式实现

  在今后工作中,如果一个类(SObject)要使用单例模式(Singleton 单例模式的类模板),只需三步骤:

  (1)类(SObject)的构造函数必须私有化;同时,拷贝构造函数、重载=操作符 也私有化;

  (2)将单例模式的类模板声明为这个类的友元类; friend class Singleton<SObject>;

  (3)通过 单例模式类模板中 SObject* s = Singleton<SObject>::GetInstance(); 创建对象。

c++ 中的单例类模板的实现方法的更多相关文章

  1. C++中的单例类模板

    1,本节课讲述单例类模式,实现并抽取相关代码实现单例类模板,在以后开发工作 中,如果想要使用单例模式,那么直接使用今天开发的单例类模板就可以: 2,需求的提出: 1,在架构设计时,某些类在整个系统生命 ...

  2. C++之单例类模板

    单例类模板:一个类只能有一个对象,比如超市收银系统中清点物品的仪器只有一个 设计思路: 1.构造函数,拷贝构造函数必须设计为private,防止自己生成新的对象 2.且类的指针要设计为static类型 ...

  3. C++解析(27):数组、智能指针与单例类模板

    0.目录 1.数组类模板 1.1 类模板高效率求和 1.2 数组类模板 1.3 堆数组类模板 2.智能指针类模板 2.1 使用智能指针 2.2 智能指针类模板 3.单例类模板 3.1 实现单例模式 3 ...

  4. 28.C++- 单例类模板(详解)

    单例类 描述 指在整个系统生命期中,一个类最多只能有一个实例(instance)存在,使得该实例的唯一性(实例是指一个对象指针)  , 比如:统计在线人数 在单例类里,又分为了懒汉式和饿汉式,它们的区 ...

  5. iOS中编写单例类的心得

    单例 1.认识过的单例类有哪些: NSUserDefaults.NSNotificationCenter.NSFileManager.UIApplication 2.单例类 单例类某个类在代码编写时使 ...

  6. Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践

    Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践 背景 很多开发者或者有经验的老手都会建议尽量不要用单例模式,这是有原因的. 单例模式是设计模式中最简单的也是大家通常最先接触的一种设计 ...

  7. [转]单例模式——C++实现自动释放单例类的实例

    [转]单例模式——C++实现自动释放单例类的实例 http://www.cnblogs.com/wxxweb/archive/2011/04/15/2017088.html http://blog.s ...

  8. 单例类singleton自动释放

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  9. 《Effective Java》 读书笔记(三) 使用私有构造方法或枚举实现单例类

    1.单例类到现在为止算是比较熟悉的一种设计模式了,最开始写单例模式是在C#里面,想要自己实现一个单例类,代码如下: public class Instance { private static rea ...

随机推荐

  1. 吴裕雄--天生自然python学习笔记:人脸识别用到的特征文件haarcascade_frontalface_default.xml下载

    下载地址:https://github.com/opencv/opencv/tree/master/data/haarcascades 1.找到haarcascade_frontalface_defa ...

  2. 对TD tree的使用体验及建议

    TDtree与QQ空间有着相似的功能,你可以在里面发表自己的感受与心情,也可以存储照片或者给喜欢的说说点赞.发表评论等,可以说这是一个将QQ空间从QQ里独立出来的软件.作为一个娱乐性的软件,它的功能还 ...

  3. Android内存调优的一些方法

    一.巧妙使用软引用和弱引用 软引用,系统内存紧张时会回收软引用对象,一般用用高速缓存,例如图片缓存,我们一般通过内存缓存图片来提高图片加载速度,但内存吃紧的时候可以通过软引用及时对图片资源回收. 弱引 ...

  4. iOS UITableView Tips(2)

    #TableView Tips(2) (本来想一章就结束TableView Tips,但是发现自己还是太天真了~too young,too simple) ##架构上的优化 在Tips(1)中指出了一 ...

  5. E丢丢App重设计总结

    E丢丢学习App是华夏大地教育可以有限公司旗下的一款产品,专为提升学历者打造,它整合了线上+跟踪的 (E平台)功能,方便工作人员随时随地管理账号.跟进学员:同时还可以随时了解教育行业的新闻资讯.一对一 ...

  6. 实现api开发实例页面

    主要实现功能: 1.通过点击不同的option选项,自动生成不同的代码. 功能分析: 1.点击不同的option选项,这里其实就是使用了一个事件即onchange,把这个事件放在<select& ...

  7. 吴裕雄--天生自然python学习笔记:Python3 函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这 ...

  8. Ubuntu gnome安装Monaco字体,FontForge module is probably not installed

    首先下载原始Monaco字体,注意我只找到了这一款在ubuntu的gnome下可见,其他的各种monaco即使安装了也看不到. https://gist.github.com/epegzz/16342 ...

  9. Nginx笔记总结二十:nginx索引目录配置

    location / { autoindex on; autoindex_localtime on; }

  10. Ionic3学习笔记(十五)自定义 tab icon

    本文为原创文章,转载请标明出处 美工做了一套 icon,自然是要用的.将 icon copy 到 assets 文件夹下. 例如 .icon-ios-home-custom 为 iOS icon 选中 ...