C++实现设计模式---享元模式 (Flyweight)

享元模式 (Flyweight)

享元模式 是一种结构型设计模式,它通过共享对象来减少内存使用和对象创建的开销。当系统中有大量相似对象时,享元模式可以避免重复创建相同对象,从而节省内存。


意图

  • 通过共享相同对象来减少内存消耗。
  • 用于系统中存在大量相似对象的场景。

使用场景

  1. 大量相似对象

    • 系统中存在许多共享的对象,这些对象的状态大部分是相同的。
  2. 状态可以分为内部状态和外部状态

    • 内部状态:可以被共享的部分,不会随上下文变化。
    • 外部状态:特定于场景的部分,不可共享,需要由客户端管理。
  3. 节约内存

    • 系统需要大量创建对象,但内存开销成为瓶颈。

参与者角色

  1. 享元接口 (Flyweight)

    • 定义共享对象的公共接口。
  2. 具体享元 (ConcreteFlyweight)

    • 实现享元接口,存储可以共享的内部状态。
  3. 非共享享元 (UnsharedFlyweight)

    • 不可以共享的子类,通常会组合共享的享元对象。
  4. 享元工厂 (FlyweightFactory)

    • 创建并管理享元对象,确保共享对象的唯一性。
  5. 客户端 (Client)

    • 负责管理外部状态,并将外部状态与享元对象结合使用。

示例代码

以下代码展示了如何使用享元模式来共享图形对象,例如圆形。

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>// 享元接口:图形
class Shape {
public:virtual ~Shape() = default;virtual void draw(const std::string& color) const = 0; // 外部状态为颜色
};// 具体享元类:圆形
class Circle : public Shape {
private:int radius; // 内部状态:半径public:Circle(int r) : radius(r) {}void draw(const std::string& color) const override {std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;}
};// 享元工厂:管理享元对象
class ShapeFactory {
private:std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象public:std::shared_ptr<Shape> getCircle(int radius) {if (shapes.find(radius) == shapes.end()) {shapes[radius] = std::make_shared<Circle>(radius);std::cout << "Creating a circle with radius " << radius << std::endl;}return shapes[radius];}
};// 客户端代码
int main() {ShapeFactory factory;// 获取共享的圆形对象auto circle1 = factory.getCircle(5);auto circle2 = factory.getCircle(10);auto circle3 = factory.getCircle(5); // 共享对象// 使用享元对象绘制circle1->draw("red");   // 外部状态:红色circle2->draw("blue");  // 外部状态:蓝色circle3->draw("green"); // 外部状态:绿色return 0;
}

代码解析

1. 享元接口 (Shape)
  • 定义了 draw 方法,用于绘制图形,并接收外部状态作为参数:
class Shape {
public:virtual ~Shape() = default;virtual void draw(const std::string& color) const = 0;
};
2. 具体享元类 (Circle)
  • 实现了 Shape 接口,存储可以共享的内部状态(如半径):
class Circle : public Shape {
private:int radius; // 内部状态public:Circle(int r) : radius(r) {}void draw(const std::string& color) const override {std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;}
};
3. 享元工厂 (ShapeFactory)
  • 负责管理享元对象,保证相同的内部状态只创建一个对象:
class ShapeFactory {
private:std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象public:std::shared_ptr<Shape> getCircle(int radius) {if (shapes.find(radius) == shapes.end()) {shapes[radius] = std::make_shared<Circle>(radius);std::cout << "Creating a circle with radius " << radius << std::endl;}return shapes[radius];}
};
4. 客户端
  • 客户端通过 ShapeFactory 获取共享对象,并将外部状态与内部状态结合:
auto circle1 = factory.getCircle(5); // 创建新对象
auto circle3 = factory.getCircle(5); // 复用已有对象
circle1->draw("red");   // 绘制红色圆形
circle3->draw("green"); // 绘制绿色圆形

优缺点

优点
  1. 减少内存使用
    • 通过共享对象,避免了重复创建相同对象,节省了内存。
  2. 提高系统性能
    • 减少了对象创建的时间和空间开销。
  3. 灵活性高
    • 外部状态与内部状态分离,可以独立管理。
缺点
  1. 复杂性增加
    • 系统需要额外的享元工厂来管理共享对象。
  2. 外部状态的管理困难
    • 客户端需要显式传递外部状态,增加了使用复杂性。

适用场景

  1. 系统有大量相似对象

    • 如文字处理系统中的字符对象,每个字符对象可以共享其字体、大小等内部状态。
  2. 内存消耗成为瓶颈

    • 系统中对象数量庞大,通过共享来减少内存占用。
  3. 对象的状态可以分为内部状态和外部状态

    • 内部状态可以共享,外部状态由客户端管理。

总结

享元模式通过共享相似对象来减少内存使用,是一种优化性能的重要模式。它适用于对象数量庞大且状态大部分可以共享的场景。

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

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

相关文章

如何在gitlab cicd中实现每月10号上午执行

在 GitLab CI/CD 中&#xff0c;可以通过设置定时触发器&#xff08;Schedules&#xff09;和脚本中的时间判断逻辑结合&#xff0c;确保任务只在每月 10 号的上午运行。 以下是实现的步骤&#xff1a; 1. 设置定时触发器 GitLab 提供了 Schedules 功能&#xff0c;可以指定每…

K8S 亲和性与反亲和性 深度好文

今天我们来实验 pod 亲和性。官网描述如下&#xff1a; 假设有如下三个节点的 K8S 集群&#xff1a; k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、镜像准备 1.1、镜像拉取 docker pull tomcat:8.5-jre8-alpine docker pull nginx…

安装指南:LLaMA Factory、AutoGPTQ 和 vllm

安装指南&#xff1a;LLaMA Factory、AutoGPTQ 和 vllm 在本文中&#xff0c;我们将详细介绍如何安装 LLaMA Factory、AutoGPTQ 和 vllm&#xff0c;这些工具在大型语言模型&#xff08;LLMs&#xff09;和视觉语言模型&#xff08;VLMs&#xff09;的微调和量化中非常有用。我…

Nginx三种不同类型的虚拟主机(基于域名、IP 和端口)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年1月15日13点14分 目录 1. 基于域名的虚拟主机 …

解析OVN架构及其在OpenStack中的集成

引言 随着云计算技术的发展&#xff0c;虚拟化网络成为云平台不可或缺的一部分。为了更好地管理和控制虚拟网络&#xff0c;Open Virtual Network (OVN) 应运而生。作为Open vSwitch (OVS) 的扩展&#xff0c;OVN 提供了对虚拟网络抽象的支持&#xff0c;使得大规模部署和管理…

C#异步和多线程,Thread,Task和async/await关键字--12

目录 一.多线程和异步的区别 1.多线程 2.异步编程 多线程和异步的区别 二.Thread,Task和async/await关键字的区别 1.Thread 2.Task 3.async/await 三.Thread,Task和async/await关键字的详细对比 1.Thread和Task的详细对比 2.Task 与 async/await 的配合使用 3. asy…

doris:导入概览

Apache Doris 提供了多种导入和集成数据的方法&#xff0c;您可以使用合适的导入方式从各种源将数据导入到数据库中。Apache Doris 提供的数据导入方式可以分为四类&#xff1a; 实时写入&#xff1a;应用程序通过 HTTP 或者 JDBC 实时写入数据到 Doris 表中&#xff0c;适用于…

【Flink系列】9. Flink容错机制

9. 容错机制 在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 9.1 检查点&#xff08;Checkpoint&#xff09; 9.1.1 检查点的保存 1&#xff09;周期性的触发保存 “随时存档”确实恢复起来方便&#xff0c;可是需要我…

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者&#xff1a;Amy MiHyun Jang创建日期&#xff1a;2020/07/28最后修改时间&#xff1a;2024/02/12描述&#xff1a;TPU 上的医学图像分类。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…

Axios 封装:处理重复调用与内容覆盖问题

问题描述&背景 下拉选择框&#xff0c;支持搜索&#xff0c;搜索时携带参数调用接口并更新下拉选项下拉选择连续进行多次搜索&#xff0c;先请求但响应时间长的返回值会覆盖后请求但响应时间短的举例&#xff1a; 搜索后先清空选项&#xff0c;再输入内容进行搜索。清空后…

openssl s_server源码剥离

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

51单片机 DS18B20温度储传感器

DS18B20温度传感器 64-BITROM&#xff1a;作为器件地址&#xff0c;用于总线通信的寻址&#xff0c;是唯一的&#xff0c;不可更改 SCRATCHPAD&#xff08;暂存器&#xff09;&#xff1a;用于总线的数据交互 EEPROM&#xff1a;用于保存温度触发阈值和配置参数 暂存器 单总线…

如何学习Transformer架构

Transformer架构自提出以来&#xff0c;在自然语言处理领域引发了革命性的变化。作为一种基于注意力机制的模型&#xff0c;Transformer解决了传统序列模型在并行化和长距离依赖方面的局限性。本文将探讨Transformer论文《Attention is All You Need》与Hugging Face Transform…

如何选择合适的服务器?服务器租赁市场趋势分析

服务器租赁市场概览 服务器租赁 market可以分为两种类型&#xff1a;按小时、按月和按年&#xff0c;每种模式都有其特点和适用场景&#xff0c;按小时租赁是最经济实惠的选择&#xff0c;适用于短期需求&#xff1b;按月租赁则适合中长期使用&#xff1b;而按年租赁则是最灵活…

[操作系统] 深入理解操作系统的概念及定位

概念 任何计算机系统都包含⼀个基本的程序集合&#xff0c;称为操作系统(OS)。 其核心功能如图片所示&#xff0c;包括&#xff1a; 内核 (Kernel)&#xff1a; 内核是操作系统的核心部分&#xff0c;被认为是狭义上的操作系统&#xff0c;直接与硬件打交道。负责进程管理、内…

Java并发编程——线程池(基础,使用,拒绝策略,命名,提交方式,状态)

我是一个计算机专业研0的学生卡蒙Camel&#x1f42b;&#x1f42b;&#x1f42b;&#xff08;刚保研&#xff09; 记录每天学习过程&#xff08;主要学习Java、python、人工智能&#xff09;&#xff0c;总结知识点&#xff08;内容来自&#xff1a;自我总结网上借鉴&#xff0…

nginx 配置代理,根据 不同的请求头进行转发至不同的代理

解决场景&#xff1a;下载发票的版式文件&#xff0c;第三方返回的是url链接地址&#xff0c;但是服务是部署在内网环境&#xff0c;无法访问互联网进行下载。此时需要进行走反向代理出去&#xff0c;如果按照已有套路&#xff0c;就是根据不同的访问前缀&#xff0c;跳转不同的…

设计一个流程来生成测试模型安全性的问题以及验证模型是否安全

要使用 Ollama 运行 llama3.3:70b 模型&#xff0c;并设计一个流程来生成测试模型安全性的问题以及验证模型是否安全&#xff0c;可以按照以下步骤进行设计和实现。整个过程包括环境配置、设计安全测试提示词、执行测试以及分析结果。以下是详细的步骤和指导&#xff1a; 1. 环…

iOS - TLS(线程本地存储)

从源码中&#xff0c;详细总结 TLS (Thread Local Storage) 的实现&#xff1a; 1. TLS 基本结构 // TLS 的基本结构 struct tls_data {pthread_key_t key; // 线程本地存储的键void (*destructor)(void *); // 清理函数 };// 自动释放池的 TLS class Autorelease…

docker在不删除容器的情况下修改端口映射

注意&#xff1a;必须先停止docker服务&#xff01;&#xff01;&#xff01;&#xff01; 1) 停止容器 2) 停止docker服务(systemctl stop docker) 3) 修改这个容器的hostconfig.json和config.v2.json文件中的端口 先查看容器id docker inspect jenkins 进入该目录 hostcon…