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. spring mvc 页面form提示语

    <form:form id="inputForm" modelAttribute="bsRabiesNum" action="${ctx}/nu ...

  2. seek for|contrary to|lag behind|take up|take advantage of|be confident of|allow for |

    There are signs ________ restaurants are becoming more popular with families.  A. that  B. which  C. ...

  3. continuing|offensive

    the fact of something continuing for a long period of timewithout being changed or stopped 连续性,持续性,连 ...

  4. python与模块的导入方式

    今日所得 模块 import from...import... 循环导入 相对导入 绝对导入 软件开发目录规范 模块 模块:是一系列功能的集合体 模块的三种来源:1.内置模块(Python解释器自带的 ...

  5. C++中stoi函数

    作用: 将 n 进制的字符串转化为十进制 头文件: #include <string> 用法: stoi(字符串,起始位置,n进制),将 n 进制的字符串转化为十进制 示例: stoi(s ...

  6. Java发送Post请求,参数JSON,接收JSON

    /** * 发送post请求 * @param url 路径 * @param jsonObject 参数(json类型) * @param encoding 编码格式 * @return * @th ...

  7. gitlab两种连接方式:ssh和http对比

    共同点: 都可以使用git clone 地址 .将项目下载到本地. 不同点: 当将本地修改上传到远程服务器时,http需要输入用户名密码,ssh. 1.ssh方式: 这是一种相对安全的方式这要求将本地 ...

  8. Java实用教程系列之对象的转型

    体现: 父类的引用可以指向子类的对象接口的引用可以指向实现类的对象转型: 向上转型由子类类型转型为父类类型,或者由实现类类型转型为接口类型向上转型一定会成功,是一个隐式转换向上转型后的对象,将只能访问 ...

  9. SWUST OJ Gold Nuggets Distribution(0490)

    Gold Nuggets Distribution(0490) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 421 Accepte ...

  10. BTCU(高校区块链联盟)-联盟链第6讲作业

    // payment project main.go package main import ( "fmt" "strconv" "github.co ...