文章目录

  • 1.概述
  • 2.简单实现
  • 3.小结
  • 参考文献

1.概述

使用设计模式可以提高代码的可复用性、可扩充性和可维护性。单例模式(Singleton Pattern),确保一个类只有一个实例,并提供一个全局访问点。

有一些类对象我们只需要一个,比方说线程池(threadpool)、缓存(cache)、对话框、注册表(registry)、日志对象,充当打印机、显卡等设备的驱动程序的对象。此时,可以使用单例模式。

单例模式类图结构:

2.简单实现

单例模式可以直接用一个全局变量,但这样的代码不够优雅,而且不能保证只能创建一个对象,也就是说除了一个全局实例外,仍然可以创建多个类的实例。《设计模式》一书中给出了一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有静态方法获取该实例。即便如此,对具体实现的细节的不同处理,单例模式有多种不同的实现方式,多种写法各有利弊,下面请看C++单例模式。

(1)急切式

class Singleton {private:Singleton(){}   //构造函数私有static Singleton pInstance;
public:static Singleton* getInstance(){return &pInstance;}
};
Singleton Singleton::pInstance;  //定义静态类对象

这种方式在进入main函数前就完成了类对象的定义,避免了多线程的同步问题,但是没有做到需要类对象时才定义,没有达到“懒惰实例化”的效果。

(2)懒惰式(线程不安全)

class Singleton{private:Singleton(){}   //构造函数私有static Singleton* pInstance;
public:static Singleton* getInstance(){if (pInstance == NULL)  //判断是否第一次调用  pInstance = new Singleton();return pInstance;}
};
Singleton* Singleton::pInstance=NULL;

这种方式延迟了类对象的实例化,在需要的时候再实例化。但上面因为没有线程同步操作,所以存在多线程不安全隐患,多个线程同时调用getInstance()时可能会创建多个类对象。

(3)懒惰式(线程安全)

HANDLE hMutex;
//使用互斥对象迁,先创建互斥对象
hMutex = CreateMutex( NULL,         //默认安全级别  FALSE,        //创建它的线程不拥有互斥对象  NULL);        //没有名字
class Singleton{private:Singleton(){}   //构造函数私有static Singleton* pInstance;
public:static Singleton* getInstance(){WaitForSingleObject(hMutex, INFINITE);  //上锁if (pInstance == NULL)  //判断是否第一次调用  pInstance = new Singleton();ReleaseMutex(hMutex);   //解锁return pInstance;}
};
Singleton* Singleton::pInstance=NULL;

这种写法能够在多线程中很好的工作,但是每次调用getInstance方法时都需要进行同步,造成不必要的同步开销,而且只有第一次创建类对象时才需要同步,所以不建议用这种写法。

(4)双重检查加锁式(Double-checked Locking,DCL)

HANDLE hMutex;
hMutex = CreateMutex( NULL,FALSE,NULL);class Singleton{private:Singleton(){}   //构造函数私有static Singleton* pInstance;
public:static Singleton* getInstance(){if (pInstance == NULL){        //判断是否第一次调用  WaitForSingleObject(hMutex, INFINITE);  //上锁if (pInstance == NULL)  pInstance = new Singleton();ReleaseMutex(hMutex);   //解锁}return pInstance;}
};
Singleton* Singleton::pInstance=NULL;

这种写法在getInstance()方法中进行了两次判空,第一次为了不必要的同步,第二次是在pInstance等于NULL的情况下才创建实例,同步操作实际上只发生了一次,大大提高了效率。

(5)局部静态变量式

class Singleton {private:Singleton(){}   //构造函数私有
public:static Singleton* getInstance(){static Singleton instance;return &instance;}
};

使用局部静态变量,非常巧妙的方法,完全实现了单例的特性,而且代码简洁优雅。

这里要注意一个问题,如果getInstance()函数返回的是类对象引用,会出现类拷贝的问题,这就违背了单例的特性。产生这个问题原因在于:编译器会为类生成一个默认的拷贝构造函数。例如下面的代码就会有问题:

Singleton singleton = Singleton::getInstance(); //getInstance()返回对象引用

解决办法是禁止编译器生成默认拷贝构造函数,或将其显示申明为私有,且使用引用接收返回的对象引用。

class Singleton {private:Singleton(){}   //构造函数私有Singleton(const Singleton&)=delete;    //禁止拷贝构造函数
public:static Singleton& getInstance(){static Singleton instance;return instance;}
};//使用引用接收返回的对象引用
Singleton& singleton=Singleton::getInstance();

3.小结

(1)单例模式,确保一个类只有一个实例,并提供一个全局访问点。
(2)在确保程序中某个类只有一个实例时,请采用单例模式,且推荐局部静态变量式写法。

有新的实现方法,会继续补充,欢迎网友留言指教!


参考文献

[1] C++中的单例模式
[2] 设计模式(二)单例模式的七种写法
[3] Head First 设计模式(中文版)

创建型设计模式(1)—— 单例模式(Singleton Pattern)相关推荐

  1. 设计模式 - 创建型模式_ 单例模式 Singleton Pattern

    文章目录 概述 特点 懒汉式单例 饿汉式单例 饿汉式和懒汉式区别 概述 新总结了一篇单例模式的(2019-02-21),看这篇就够了 并发编程-09安全发布对象的4种方式 单例模式确保某各类只有一个实 ...

  2. 【设计模式】单例模式 Singleton Pattern

    通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance)  的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...

  3. Java设计模式之单例模式(Singleton Pattern)

    **单例模式:用来创造独一无二的,只能有一个实例的对象设计模式.单例模式确保一个类只有一个实例,并提供一个全局访问点.**相比于全局变量(对对象的静态引用),单例模式可以延迟实例化,而且全局变量不能保 ...

  4. 创建型设计模式 之 单例模式

    <研磨设计模式>中的定义:保证一个类仅有一个实例,并提供它的一个全局访问点. 而单例模式的本质便是--控制实例数目. 一.介绍 1.单例模式和静态方法区别 简单的一个懒汉式单例模式 pub ...

  5. 创建型设计模式(单例模式)

    单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 一.懒汉式单例 //懒汉式单例类.在第一次调用的时候实例化自己 p ...

  6. 设计模式--创建型设计模式

    一. 设计模式的目的 ​ 编写软件过程中,可能面临来自耦合性.内聚性.可维护性.可扩展性.重用性.灵活性等多方面的挑战,设计模式是为了让程序具有更好的: 代码重用性(即相同的代码,不用多次编写) 可读 ...

  7. 《Python编程实战:运用设计模式、并发和程序库创建高质量程序》—— 第1章 Python的创建型设计模式...

    本节书摘来自华章出版社<Python编程实战:运用设计模式.并发和程序库创建高质量程序>一 书中的第1章,第1.1节,作者:(美) Mark Summerfield,更多章节内容可以访问云 ...

  8. 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)

    创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...

  9. 设计模式(创建型)之建造者模式(Builder Pattern)

    PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...

  10. 设计模式 ~ 创建型模式 ~ 工厂模式 ~ Factory Pattern。

    设计模式 ~ 创建型模式 ~ 工厂模式 ~ Factory Pattern. 文章目录 设计模式 ~ 创建型模式 ~ 工厂模式 ~ Factory Pattern. eg. 简单工厂模式. 结构. 优 ...

最新文章

  1. 显示二维数组并计算和
  2. 简单的html渲染模板引擎
  3. 任意长度的高精度大整数加法
  4. linux gui编程语言,使用 Red 语言编写 GUI 应用程序
  5. MacOS 安装 Telnet
  6. python寻路_【Python】 Numpy极简寻路
  7. 基于WPF+XMPP的IM程序开发日志 之二 WPF线程模型
  8. 编程课课程感想和建议_最佳在线编程课程
  9. 实时操作系统与非实时操作系统的区别
  10. ADO.NET数据访问模式
  11. 如何在SharePointDesigner订制页面里判断用户权限
  12. 加密php大马,webshell加密-加密你的大马
  13. 苹果手机怎么关闭爱奇艺自动续费_爱奇艺回应涨价为用户创造优质服务,小编建议用户先关闭自动续费...
  14. android筛选功能代码,Android中 TeaScreenPopupWindow多类型筛选弹框功能的实例代码
  15. 互联网,因特网和万维网的区别是什么?
  16. 浙大邮箱添加进apple_如何在Apple Mail中使用智能邮箱组织电子邮件
  17. 自媒体各大平台收益对比_各大自媒体平台的收益收益如何 以下是我个人的一个汇总...
  18. 软开面试题合集--Binrry(冰蕊)
  19. 怎么修改ftp服务器被动端口,如何设置vsftp的被动模式端口
  20. python爬取qq数据_用Python爬取QQ好友空间说说进行分析

热门文章

  1. 谷歌披露影响多个苹果操作系统的零点击Image I/O 漏洞和开源库 OpenEXR漏洞
  2. 重磅签约!成都睿铂与成都航院共建数据处理联合实验室
  3. REST无状态风格的理解
  4. 三分钟快速理解javascript内存管理
  5. 解决 mcrypt.h not found
  6. linux 基础命令 1
  7. Ant构建与部署Java项目---入门
  8. iPhone iPhoneSimulator.platform/Developer/usr/bin/clang++ failed with exit code 1 出现这种错误的原因是...
  9. VS2005-此计算机下已安装了试用版,必须先卸载以前安装的试用版后才能安装另一个试用版
  10. GDB 调试命令讲解 2-转