常见的设计模式--单例模式

设计模式

  设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的是为了代码可重用性、让代码更容易被他人理去解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

单例模式

  一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

饿汉模式

  饿汉模式就是在程序运行之前将所有的资源一次性创建好,在之后用的时候就会很方便。由于静态的变量是在进入主函数之前就创建好了,所以要定义一个静态变量,然后将构造函数和拷贝构造设置为私有的,拷贝构造函数要只声明不定义,并在类中给出一个创建对象的静态方法,这个静态方法只能是引用返回,如果值返回,就会调用拷贝构造,但是拷贝构造调不了,即使可以调就会创建一个对象,这样就和单例模式相冲突。虽然这种方式在程序运行之后不用再去创建资源,直接调用就可以,但是如果这份资源很大,那么程序就会启动的很慢。

class Singleton 
{
public:static Singleton* GetInstance(){return &p;}private://构造函数私有Singleton(){}//防止被拷贝Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
private:static Singleton p;
};Singleton Singleton::p;

  使用场景

  在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞
争,提高响应速度更好。

懒汉模式

  实现过程:
  懒汉模式就是在需要的时候才会去创建 构造函数和拷贝构造函数都要设为私有的,同样的在类中给出一个创建静态的方法,并且在类中创建一个静态的指针,在调用这个方法时如果这个静态的指针是空的,就为这个指针new一个对象,返回去。如果是在多线程的环境中,就会出现多个线程同时去申请资源,这时候就要多线程中常用的加解锁操作,如果每次都要先加锁在检测,这时候所有的线程都会阻塞在加锁这里,等解锁后才可以继续操作,所以使用DCL双检锁,这时如果有一个线程在进行加解锁操作,另一个线程也过来了,这时候资源已经申请好了,这个后来的线程就可以直接返回,不用阻塞等待之前的线程。但是这样的版本仍然是有问题的,如果线程A正在进行对象的的创建,线程B过来了,但是A现在只是申请了空间,还没有进行实例化,但是B检测到这个对象不为空,直接返回去使用,就会出问题,所以要将静态对象加一个volatile来限定一下,告诉系统每次取变量里面的信息的时候不要从寄存器中取,要到内存里面取,这样就禁止了编译器对创建对象的次序进行优化(申请空间->构造对象->赋值—>申请空间->赋值->构造对象)。虽然改进了这么多,但是这个代码还存在问题,那就是没有释放空间,可能会存在内存泄漏。如果要释放,就要保证所有的线程已经用完了这份资源,但是不能在类中直接给出一个静态的释放函数,这样有可能会忘记调用这个函数,最好的方法就是内嵌一个内部类来实现释放。

#include <mutex>
#include <thread>using namespace std;class Singleton1
{
public:volatile Singleton1* GetInstance(){if (p == nullptr)//要采用DCL双检锁,让其他的线程可以不用等,直接返回。//这样如果编译器对代码进行了优化,将创建对象的顺序重新调整,直接返回就会出错。{m_tex.lock();//如果这里只加这一个锁,然后去判断,其他线程会阻塞在这里等待解锁。if (p == nullptr)p = new Singleton1;m_tex.unlock();}return p;}//在释放资源的时候要保证所有线程已经将这份资源用完,但是不能直接在类中给出一个释放资源的函数,有可能忘记调用这个函数//最好的方法是在类中内嵌一个类负责资源释放class Clean{public:~Clean(){if (Singleton1::p){delete Singleton1::p;Singleton1::p = nullptr;}}};static Clean c;private:Singleton1(){}Singleton1(const Singleton1&) = delete;Singleton1& operator=(const Singleton1&) = delete;
private:static  Singleton1 volatile *p;static mutex m_tex;
};
//为对象添加volatile关键字,告诉系统取变量里面的信息的时候从内从中取,这样就禁止了编译器对变量的创建顺序进行优化
//但是这样还不够,就是没有释放空间,会造成内存泄漏。
volatile Singleton1* Singleton1::p = nullptr;
mutex Singleton1::m_tex;
Singleton1::Clean c;

  使用场景

  如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章搞懂数据仓库:维度表(设计原则、设计方法)

目录 1、什么是维度表&#xff1f; 2、维度表设计原则 &#xff08;1&#xff09;维度属性尽量丰富&#xff0c;为数据使用打下基础 &#xff08;2&#xff09;给出详实的、富有意义的文字描述 &#xff08;3&#xff09;区分数值型属性和事实 &#xff08;4&#xff09;…

javascript 键值转换

for (var i 0; i < headerFields.length; i) {fieldToIndex[headerFields[i]] i;} 转载于:https://www.cnblogs.com/EasonSun/archive/2012/08/03/2621661.html

Github项目:AI消除马赛克实战

目录 1、原理 2、准备工作 3、消除马赛克 4、效果对比 1、原理 该算法利用线性盒滤波器分别处理每个块的事实。对于每个块&#xff0c;它将搜索图像中的所有块像素化以检查直接匹配。 对于大多数像素化图像&#xff0c;Depix能够找到单个匹配结果。它假设这些是正确的。然…

C++继承一览

继承的概念及定义 继承机制是面向对象程序设计是代码可以复用的重要手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生的类称为派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体现了由简单到复杂的认知过程。…

人工智能能否复制人脑引争论 美媒:目前AI仍存在局限性

来源&#xff1a;网易智能摘要&#xff1a;人们应用人工智能技术&#xff08;AI&#xff09;的所有领域&#xff0c;包括无人驾驶汽车、机器人医生、超过10亿中国公民的社会信用评分系统等&#xff0c;当前都取决于一场关于如何让AI做其不能做的事的辩论。8月6日报道称&#xf…

Tushare免费获取股票数据:实时数据,历史数据,行情数据

一 操作手册 引导用户顺利开始使用Tushare Pro数据&#xff0c;以下步骤将带您开始Tushare数据之旅&#xff1a; 用户注册登录后可调用数据&#xff1a;https://tushare.pro/register?reg399205 二 如何获取TOKEN凭证 1、登录成功后&#xff0c;点击右上角->个人主页 2、…

2012/8/3 Extjs使用TabPanel时需要注意的问题

在创建Ext.TabPanel时&#xff0c;配置项deferredRender经常会被忽略&#xff0c;关于这个配置项&#xff0c;我们来看一下API文档的解释&#xff1a;“内置地&#xff0c;Tab面板是采用Ext.layout.CardLayout的方法管理tabs。此属性的值将会传递到布局的Ext.layout.CardLayout…

排序(冒泡、选择、插入、希尔、快排、堆排、归并)

冒泡排序 冒泡排序时通过无序区中相邻记录的关键字间的比较和位置的交换&#xff0c;使关键字最小的元素如气泡似的逐步上浮直水面。有序区逐渐扩大&#xff0c;无序区逐渐缩小。   冒泡排序算法的原理如下&#xff1a; 比较相邻的元素。如果第一个比第二个大&#xff0c;就…

人民日报:人工智能,务实发展是正道

来源&#xff1a;人民日报摘要&#xff1a;近日&#xff0c;由中国人工智能学会主办的中国人工智能大会在深圳召开&#xff0c;利用这个人工智能领域产、学、研紧密结合的高端前沿交流平台&#xff0c;围绕关键核心技术发展等当前热点话题&#xff0c;学者和业界人士进行了充分…

kudu参数优化设置,让集群飞起来~

根据数据体量&#xff0c;结合集群各节点的CPU、内存、磁盘的表现&#xff0c;合理优化设置kudu参数&#xff0c;让集群飞起来~ 如有雷同&#xff0c;纯属借鉴~ 1.Kudu后台对数据进行维护操作&#xff0c;如写入数据时的并发线程数&#xff0c;一般设置为4&#xff0c;官网建议…

(转)Some awareness before migrating from x86 to x64

本文转自&#xff1a;http://www.cnblogs.com/feishunji/archive/2010/10/20/1856798.html Lets assume we have the following three dlls: anycpu.dll -- compiled "any cpu" x86.dll -- compiled "x86" x64.dll -- compiled &…

大数据技术Hbase 和 Hive 详解

目录 两者的特点 各自的限制 应用场景 大数据技术Hbase 和 Hive 详解&#xff0c; 今天给大家介绍一下关于零基础学习大数据视频教程之HBASE 和 HIVE 是多么重要的技术&#xff0c;那么两者有什么区别呢 ? 下面我们一起来看一下吧。 ApacheHive 是一个构建在 hadoop 基础设…

STL中vector和list的区别

底层结构 vector的底层结构是动态顺序表&#xff0c;在内存中是一段连续的空间。   list的底层结构是带头节点的双向循环链表&#xff0c;在内存中不是一段连续的空间。 随机访问 vector支持随机访问&#xff0c;可以利用下标精准定位到一个元素上&#xff0c;访问某个元素的…

自动驾驶芯片:GPU 的现在和 ASIC 的未来

来源&#xff1a;乐晴智库精选▌车载芯片的发展趋势(CPU-GPU-FPGA-ASIC)过去汽车电子芯片以与传感器一一对应的电子控制单元(ECU)为主&#xff0c;主要分布与发动机等核心部件上。随着汽车智能化的发展&#xff0c;汽车传感器越来越多&#xff0c;传统的分布式架构逐渐落后&…

WAMP PHP开发环境

下载地址&#xff1a;php100.com 安装成功标志&#xff1a;访问localhost能够看到WampServer页面 步骤&#xff1a;(1)新建虚拟目录 php100 (2)在php100下新建test.php文件&#xff0c;用nodepad打开,输入PHP脚本 <?php echo "hello world"; ?>(3)localho…

C++多态面试题汇总

总结了一些常见的面试题&#xff0c;通过查阅资料给出了一些浅薄的解析&#xff0c;欢迎各位批评指教。 1. inliine函数可以实虚函数码&#xff1f; 不可以&#xff0c;因为inline函数没有地址&#xff0c;无法将他存放到虚函数表中。 2. 静态成员可以是虚函数吗&#xff1f…

电动汽车:新一轮三年十倍,“补贴”结束“高端”开启

来源&#xff1a;乐晴智库精选摘要&#xff1a;从最早的十城千辆新能源车示范推广&#xff0c;到2014年正式启动的二级市场新能源车大行情&#xff0c;再到当下新能源乘用车型的快速升级迭代&#xff0c;新能源汽车产业发展和投资已历经8余年。▌新能源汽车投资&#xff0c;推倒…

使用easyUI给datagrid添加pagination

author YHC 这个示例展示我们如何从服务器端加载数据和如何添加pagination 到datagrid. 查看 Demo 创建 DataGrid 从服务器端加载数据, 你应该设置url属性, 在你的服务器端你应该返回JSON格式数据.请看datagrid文档得到更多关于它的数据格式信息. <table id"tt" c…

一篇文章搞懂数据仓库:四种常见数据模型(维度模型、范式模型等)

目录 写在前面 一、为什么要进行数据仓库建模&#xff1f; 二、四种常见模型 2.1 维度模型 2.1.1 星型模型 2.1.2 雪花模型 2.1.3 星座模型 2.2 范式模型 2.3 Data Vault模型 2.4 Anchor模型 三 数据模型的评价标准 小编有话 写在前面 大数据时代&#xff0c;维度…

学习C语言可以从以下几个方面入手

学习C语言可以从以下几个方面入手&#xff1a; 了解基础知识&#xff1a;首先&#xff0c;你需要了解C语言的基本语法和规则&#xff0c;包括变量、数据类型、运算符、控制结构等。可以通过阅读相关的教材或在线教程来学习这些基础知识。动手实践&#xff1a;理论知识的学习是…