23种设计模式(十一)对象性能之单件模式
本系列所有文章来自李建忠老师的设计模式笔记,系列如下:
设计模式(一)面向对象设计原则
23种设计模式(二)组件协作之模板方法
23种设计模式(三)组件协作之策略模式
23种设计模式(四)组件协作之观察者模式
23种设计模式(五)单一职责之装饰模式
23种设计模式(六)单一职责之桥模式
23种设计模式(七)对象创建之工厂方法
23种设计模式(八)对象创建之抽象工厂
23种设计模式(九)对象创建之原型模式
23种设计模式(十)对象创建之构建器
23种设计模式(十一)对象性能之单件模式
23种设计模式(十二)对象性能之享元模式
23种设计模式(十三)接口隔离之门面模式
23种设计模式(十四)接口隔离之代理模式
23种设计模式(十五)接口隔离之适配器
23种设计模式(十六)接口隔离之中介者
23种设计模式(十七)状态变化之状态模式
23种设计模式(十八)状态变化之备忘录
23种设计模式(十九)数据结构之组合模式
23种设计模式(二十)数据结构之迭代器
23种设计模式(二十一)数据结构之职责链
23种设计模式(二十二)行为变化之命令模式
23种设计模式(二十三)行为变化之访问器
23种设计模式(二十四)领域规则之解析器
文章目录
- 动机
- 模式定义
- 要点总结
之前所述的方法都是在通过抽象的设计来实现松耦合的设计。面向对象很好地解决了“抽象”的问题,但是不可避免地要付出一定的代价。比如抽象里面有虚函数和继承,虚函数带来的内存的消耗还是比较多的。
对于通常情况来讲,这些消耗都可以忽略不计,但是在某些情况下,面向对象所带来的成本必须谨慎处理。
动机
在软件系统中,经常有这样一些特殊类,必须保证它们在系统中只存在一个实例,才能确保他们的逻辑正确性,以及良好的效率。
如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
- Singleton.cpp
class Singleton{private:Singleton();Singleton(const Singleton& other);
public:static Singleton* getInstance();static Singleton* m_instance;
};Singleton* Singleton::m_instance=nullptr;//线程非安全版本
Singleton* Singleton::getInstance() {if (m_instance == nullptr) {m_instance = new Singleton();}return m_instance;
}
上述这种实现在多线程的情况下并不安全。解决这种情况可以加锁,但是锁的代价太大,因为每次访问都会被锁。
//线程安全版本,但锁的代价过高
Singleton* Singleton::getInstance() {Lock lock;if (m_instance == nullptr) {m_instance = new Singleton();}return m_instance;
}
加双检查锁(锁前锁后双检查)就可以避免上述这个问题:
//双检查锁,但由于内存读写reorder不安全
Singleton* Singleton::getInstance() {if(m_instance==nullptr){Lock lock;if (m_instance == nullptr) {m_instance = new Singleton();}}return m_instance;
}
上述这种实现仍然会存在一些问题。线程是在指令层次抢时间片,也就是m_instance = new Singleton();
这一行代码可能会先分配内存,然后把内存地址给m_instance
,然后再执行构造器。这样的话就会存在问题,当线程1还没有执行构造函数,但是已经有了地址m_instance
之后,另外一个线程进来发现m_instance
不是nullptr
就直接返回了这个地址。但是这个地址是不能用的,因为还没有调用构造器。
解决办法:
//C++ 11版本之后的跨平台实现 (volatile)
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;Singleton* Singleton::getInstance() {Singleton* tmp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire);//获取内存fenceif (tmp == nullptr) {std::lock_guard<std::mutex> lock(m_mutex);tmp = m_instance.load(std::memory_order_relaxed);if (tmp == nullptr) {tmp = new Singleton;std::atomic_thread_fence(std::memory_order_release);//释放内存fencem_instance.store(tmp, std::memory_order_relaxed);}}return tmp;
}
模式定义
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
要点总结
Singleton
模式中的实力构造器可以设置为protected
以允许子类派生。
Singleton
模式一般不要支持拷贝构造函数和Clone
接口,因为这有可能导致多个对象实例,与Singleton
模式的初衷违背。
23种设计模式(十一)对象性能之单件模式相关推荐
- C++23种设计模式(1)-工厂方法模式
C++常用的设计模式有23种. 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享 ...
- 23种设计模式,今天来聊聊模板模式,工厂方法模式,单例模式。
23种设计模式,今天来聊聊模板模式,工厂方法模式,单例模式. 1. 随处可见的模板模式 2. 暗含讲究的工厂方法模式 3. 单例模式隐含的坑你能看到第几层? 视频讲解如下,点击观看: [干货篇]23种 ...
- 23种设计模式【全】 包含:模式定义 使用场景 实现步骤 优缺点 模式区别 UML类图 示例代码 注意项等
23种设计模式(全) ***项目地址***:[GitHub](https://github.com/yjhroot/design-pattern) 声明 模式分类(3大类) 创建型模式(共5种) 结构 ...
- 23种设计模式(十四)模板方法模式(阁瑞钛伦特软件-九耶实训)
常说的设计模式是23种设计模式,分为3大类: 创建型模式5种:工厂方法.抽象工厂.单例.建造者.原型 结构型模式7种:适配器.代理.桥接.装饰者.外观.享元.组合 行为型模式11种:模板方法.解释器. ...
- 23种设计模式(二十三)访问者模式(阁瑞钛伦特软件-九耶实训)
常说的设计模式是23种设计模式,分为3大类: 创建型模式5种:工厂方法.抽象工厂.单例.建造者.原型 结构型模式7种:适配器.代理.桥接.装饰者.外观.享元.组合 行为型模式11种:模板方法.解释器. ...
- 23种设计模式(7):原型模式
本文主要介绍设计模式中的原型模式. 现在电子账单越来越流行了,比如你的信用卡,到月初的时候银行就会发一份电子邮件到你邮箱中,说你这个月消费了多少,什么时候消费的,积分是多少等等,这是每个月发一次,还有 ...
- 23种设计模式(6):代理模式
先看一个例子,是有关于打游戏杀怪兽的. //先定义一个游戏者接口 public interface IGamePlayer {//登陆游戏public void login(String user, ...
- 23种设计模式(15):备忘录模式
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 类型:行为类 类图: 我们在编程的时候,经常需要保存对象的中间状态,当需要的时 ...
- C++23种设计模式(22)-中介者模式
中介者模式:用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互.中介者模式的例子很多,大到联合国安理会,小到房屋中介,都扮演了 ...
- 23种设计模式之-----简单工厂(静态工厂)模式(SimpleFactory Pattern)
这里引用 https://www.kailing.pub/PdfReader/web/viewer.html?file=24DesignPattern 讲解设计模式一文中的例子. 这个例子很形象而且通 ...
最新文章
- 让人又爱又恨的Mysql多表查询
- hadoop 1.2.1 安装步骤 伪分布式
- vue+vant 移动端H5 商城项目_01
- 计算机开机不正常运行,win7 64位旗舰版电脑开机启动不正常怎么办
- python 多线程读写文件_python多线程写入文件问题
- 《图解算法》第九章之动态规划
- 旋风解析磁力php,2018年免费引擎和正版旋风四核引擎棋力测试分析
- 编码(decode与encode)
- 在线全网音乐搭建源码_支持下载
- ​ZMC运动控制器SCARA机械手应用快速入门
- SylixOS移植Redis库总结
- Nginx的软件架构
- 程序员怎么接单赚外快,去这6个平台就可以了!
- 大学生活:计算机专业学生在大学四年内可以做些什么来丰富简历?
- 百度与吉利联合制造智能电动汽车;霍尼韦尔2020年度10大创新科技揭晓 | 美通企业日报...
- HBaseCon亚洲2018峰会盛大开幕 阿里带你洞悉HBase大数据生态最新发展和行业实践
- Attempted import error: ‘Redirect‘ is not exported from ‘react-router-dom‘ (imported as ‘Redirect‘)
- ios 11 屏幕适配问题!
- JDK的安装与环境变量配置详细教程
- ASP.NET商品进销存管理系统【附项目下载地址】