【c++设计模式14】结构型6:享元模式(Flyweight Pattern)

【c++设计模式14】结构型6:享元模式(Flyweight Pattern)

  • 一、定义
  • 二、适用场景
  • 三、过程
  • 四、享元模式类图
  • 五、C++示例代码
  • 六、使用注意事项

类型序号设计模式描述
结构型1适配器模式
(Adapter Pattern)
它用于在不修改已有类的情况下,将其接口转换为客户端所期望的接口。
2桥接模式
(Bridge Pattern)
实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。
3组合模式
(Composite Pattern)
将对象组合成树状结构来表示“部分-整体”的层次结构。
4装饰模式
(Decorator Pattern)
它允许你在不改变现有对象结构的情况下,动态地将责任(功能)附加到对象上。
5外观模式
(Facade Pattern)
对一个子系统的接口.它提供了一个简化的接口,用于访问复杂系统中的一组接口。
6享元模式
(Flyweight Pattern)
对象的存储开销,它通过共享对象来减少内存使用和提高性能
7代理模式
(Proxy Pattern)
它提供了一个代理类来控制对于原始对象的访问

一、定义

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能。享元模式将对象分为两部分:内部状态(Intrinsic State)和外部状态(Extrinsic State)。其中,内部状态是可以共享的,而外部状态是不可共享的。

二、适用场景

享元模式适用于以下情况:

  • 当应用程序需要创建大量的相似对象,并且这些对象之间存在较多的共享内部状态时,可以使用享元模式来减少内存占用。
  • 当需要缓存对象以提高系统性能时,可以使用享元模式来实现对象的重用。

三、过程

享元模式的过程包括以下几个步骤:

  • 创建享元工厂类(FlyweightFactory):享元工厂类负责创建和管理享元对象,它维- 护一个享元池(Flyweight Pool),用于缓存已创建的享元对象。std::vector<Phone*> phones
  • 定义享元接口(Flyweight):享元接口定义了享元对象的公共方法,可以是抽象类或接口。这些方法可以接受外部状态作为参数。
  • 实现具体享元类(ConcreteFlyweight):具体享元类(Phone)实现了享元接口,并包含内部状态。具体享元类可以被共享和重用。
  • 客户端使用享元对象:客户端通过享元工厂类获取或创建享元对象,然后调用享元对象的方法,传入外部状态。

四、享元模式类图

  • 享元模式中的享元类可以有子类也可以没有
  • 享元模式中可以添加享元工厂也可以不添加
  • 享元工厂的作用和单例模式类似,但二者的关注点略有不同
    • 单例模式关注的是类的对象有且只有一个
    • 享元工厂关注的是某个实例对象是否可以共享
      在这里插入图片描述

五、C++示例代码

以下是一个使用享元模式的示例代码,在这个示例中,我们将以电子设备制造为例,展示如何使用享元模式来减少内存占用:

  • 内部状态:型号是可以共享的
  • 外部状态:序列号是不可共享的,不共享的也可以提取成一个类,这个不共享的继承共享的类。
#include <iostream>
#include <unordered_map>// 享元接口:电子设备
class ElectronicDevice {
public:virtual void displayInfo(const std::string& serialNumber) = 0;
};// 具体享元类:手机
class Phone : public ElectronicDevice {
private:std::string model;public:Phone(const std::string& model) : model(model) {}void displayInfo(const std::string& serialNumber) override {std::cout << "Model: " << model << ", Serial Number: " << serialNumber << std::endl;}
};// 享元工厂类:电子设备工厂
class ElectronicDeviceFactory {
private:std::unordered_map<std::string, ElectronicDevice*> flyweights;public:ElectronicDevice* getPhone(const std::string& model) {if (flyweights.find(model) == flyweights.end()) {flyweights[model] = new Phone(model);}return flyweights[model];}
};int main() {ElectronicDeviceFactory deviceFactory;// 内部状态:型号是可以共享的ElectronicDevice* phone1 = deviceFactory.getPhone("iPhone X");ElectronicDevice* phone2 = deviceFactory.getPhone("iPhone X");ElectronicDevice* phone3 = deviceFactory.getPhone("Pixel 5");// 外部状态:序列号是不可共享的,不共享的也可以提取成一个类,这个不共享的继承共享的phone1->displayInfo("123456");phone2->displayInfo("654321");phone3->displayInfo("987654");phone3->displayInfo("123");return 0;
}

输出

在这里插入图片描述

在上述示例中,我们定义了一个享元接口 ElectronicDevice,具体享元类 Phone 实现了该接口。Phone 类中包含了内部状态 model,即手机型号。

享元工厂类 ElectronicDeviceFactory 负责创建和管理享元对象。在 getPhone 方法中,我们通过遍历 phones 容器来查找是否已经有该型号的手机。如果有,则直接返回共享对象;如果没有,则创建一个新的手机对象,并将其添加到 phones 容器中。

在 main 函数中,我们通过 ElectronicDeviceFactory 创建了三个电子设备对象,其中两个是相同型号的手机。通过调用 displayInfo 方法,我们可以看到输出的结果中共享了相同型号的手机对象。

六、使用注意事项

享元模式可以减少内存占用,但增加了系统的复杂性。需要权衡共享的程度和复杂性之间的关系,避免过度共享导致维护困难。
外部状态(Extrinsic State)是不可共享的,因此在使用享元模式时,需要将外部状态作为参数传递给享元对象的方法。——或者建立一个不共享的类,来继承共享的类。
注意线程安全性,特别是当享元对象在多个线程中被并发访问时。

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

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

相关文章

MS2351M——RF 检测器/控制器

产品简述 MS2351M 是一款对数放大器芯片&#xff0c;主要用于接收信号强度 指示 RSSI 与功率放大器控制&#xff0c;工作频率范围是 50M  3000MHz &#xff0c; 因频率与温度不同&#xff0c;动态范围达 35dB 到 45dB 。 MS2351M 是电压响应器件&#xff0c; 50M…

关于Java并发多线程的一点思考

写在开头 在过去的2023年双11活动中&#xff0c;天猫的累计访问人次达到了8亿&#xff0c;京东超60个品牌销售破10亿&#xff0c;直播观看人数3.0亿人次&#xff0c;订单支付频率1分钟之内可达百万级峰值&#xff0c;这样的瞬间高并发活动&#xff0c;给服务端带来的冲击可想而…

WPF真入门教程31--WPF版房屋租售系统

1、教程回顾 到现在为止&#xff0c;“蒸”入门系列教程已完成了30刺由浅入深地讲解&#xff0c;当然不可能讲到了WPF的所有技能点&#xff0c;但读者看到了wpf的内部各种功能及之间的联系&#xff0c;在此基础上&#xff0c;再提供一个完整有效的综合项目&#xff0c;本项目采…

实用干货:分享一个自动切换输入法的IDE插件

大家好&#xff0c;我是大澈&#xff01; 本文约1100字&#xff0c;整篇阅读大约需要3分钟。 关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费加入问答群&#xff0c;一起交流技术难题与未来&#xff01; 现在关注公众号&#xff0c;免费送你 ”前后端入行大礼包…

DHCP自动获取IP地址实验(思科·)

华为设备参考&#xff1a; 一&#xff0c;实验目的 路由器搭载DHCP&#xff0c;让PC通过DHCP自动获取IP地址 二&#xff0c;不划分vlan 1&#xff0c;实验拓扑 2&#xff0c;配置命令 Switch Switch>enable Switch#configure terminal Switch(config)#int f0/1 Switch(…

Jmeter事务控制器聚合报告

Jmeter 事务控制器。 在Jmeter中&#xff0c;默认一个取样器就是一个事务事务控制器控制其子集取样器&#xff0c;合并为一个事务 添加&#xff1a;逻辑控制器/Logic Controller -> 事务控制器/Transaction Controller TPS: 服务器每秒处理的事务数在事务控制器下添加多个…

数据结构与算法-希尔排序

引言 在计算机科学中&#xff0c;数据结构和算法是构建高效软件系统的基石。而排序算法作为算法领域的重要组成部分&#xff0c;一直在各种应用场景中发挥着关键作用。今天我们将聚焦于一种基于插入排序的改进版本——希尔排序&#xff08;Shell Sort&#xff09;&#xff0c;深…

smardaten数据报表功能全新上线,迎战“中国式报表”!

数据报表是企业业务数据统计分析最主要的应用方式之一。 面对复杂多元的报表结构、大量的数据处理需求时&#xff0c;“中国式报表”依然是业务人员、特别是财务人员进行数据统计分析的主要方式。虽然绝大多数企业都已部署高效的BI平台&#xff0c;但报表统计与可视化BI之间的…

接口测试—Postman详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、为何使用postman postman是一款简单高效的接口测试工具&#xff0c;能够很方便发送接口请求…

论文速览 | MobiSys 2018 | AIM: 通过智能手机实现声学成像 | AIM: Acoustic Imaging on a Mobile

无线感知/雷达成像部分最新工作<持续更新>: 链接地址 注1:本文系“无线感知论文速递”系列之一,致力于简洁清晰完整地介绍、解读无线感知领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; MobiCom, Sigcom, MobiSys, NSDI, SenSys, Ubicomp; JSAC, 雷达学报…

我的NPI项目之Android 安全系列 -- Keymaster到底是个什么

最近因为一直在调研独立secure element集成的工作&#xff0c;不巧的是目前使用的高通平台只有NFC-eSE的方案。高通目前也并不支持独立的eSE集成&#xff0c;codebase中并无相对应的代码。举个例子&#xff0c;目前使用的STM的一款eSE&#xff0c;但是这款eSE的开发STM还没有完…

TQ15EG开发板教程:创建运行petalinux2019.1

工程网盘链接&#xff1a;https://pan.baidu.com/s/1vFRpzmbifXt7GypU9aKjeg 提取码&#xff1a;0ylh 首先需要使用与petalinux相同版本的vivado创建工程&#xff0c;与之前不同的是在创建硬件设计时需要勾选上添加bit文件&#xff0c;所以要在生成bit文件之后再创建硬件设计…