当前位置: 首页 > news >正文

设计模式14-享元模式

设计模式14-享元模式

  • 由来动机
  • 定义与结构
  • 代码推导
  • 特点
  • 享元模式的应用
  • 总结
    • 优点
    • 缺点
    • 使用享元模式的注意事项

由来动机

在很多应用中,可能会创建大量相似对象,例如在文字处理器中每个字符对象。在这些场景下,如果每个对象都独立存在,将会导致巨大的内存开销。那么如何在避免大量颗粒度对象问题的同时,让外部客户程序仍然能够透明的使用面向对象的方式来进行操作呢?享元模式的主要动机是通过共享相似对象来减少内存使用,提高系统性能,来解决此类问题。

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

  • 应用程序使用大量相同或相似对象。
  • 对象的大部分状态可以外部化,从而使得许多对象能够共享同一个实例。
  • 需要支持大量细粒度对象高效地共享和复用。

定义与结构

模式定义: 运用共享技术有效地支持大量细粒度的对象。–《设计模式》GoF

享元模式由以下几个主要角色组成:

  1. Flyweight(享元接口): 定义了对象的接口,可以接受外部状态。
  2. ConcreteFlyweight(具体享元): 实现Flyweight接口,并为内部状态(不变部分)进行存储。
  3. UnsharedConcreteFlyweight(非共享享元): 并不是所有的Flyweight子类都需要被共享,非共享Flyweight类可以实现Flyweight接口,但它们不是共享的。
  4. FlyweightFactory(享元工厂): 创建并管理Flyweight对象,确保合理地共享Flyweight。

以下是享元模式的UML图:
在这里插入图片描述

代码推导

下面我们通过C++代码示例来实现享元模式。

  1. 定义Flyweight接口:
class Flyweight {
public:virtual void operation(int extrinsicState) = 0;virtual ~Flyweight() = default;
};
  1. 实现具体享元类:
#include <iostream>class ConcreteFlyweight : public Flyweight {
private:int intrinsicState;public:ConcreteFlyweight(int state) : intrinsicState(state) {}void operation(int extrinsicState) override {std::cout << "Intrinsic State: " << intrinsicState << ", Extrinsic State: " << extrinsicState << std::endl;}
};
  1. 实现享元工厂类:
#include <unordered_map>
#include <memory>class FlyweightFactory {
private:std::unordered_map<int, std::shared_ptr<Flyweight>> flyweights;public:std::shared_ptr<Flyweight> getFlyweight(int key) {if (flyweights.find(key) == flyweights.end()) {flyweights[key] = std::make_shared<ConcreteFlyweight>(key);}return flyweights[key];}
};
  1. 使用享元模式:
int main() {FlyweightFactory factory;std::shared_ptr<Flyweight> fw1 = factory.getFlyweight(1);std::shared_ptr<Flyweight> fw2 = factory.getFlyweight(2);std::shared_ptr<Flyweight> fw3 = factory.getFlyweight(1); // Reuses the existing Flyweightfw1->operation(10);fw2->operation(20);fw3->operation(30);return 0;
}

特点

  1. 共享对象: 通过共享细粒度对象,减少内存使用,提高性能。
  2. 内部状态和外部状态: 将对象的状态分为内部状态和外部状态,内部状态存储在享元对象中,而外部状态由客户端传入。
  3. 不可变性: 享元对象是不可变的,确保共享时不会被其他对象修改。
  4. 工厂管理: 使用享元工厂管理享元对象的创建和共享,确保唯一实例。

享元模式的应用

享元模式在以下场景中非常有用:

  1. 文本处理: 文本编辑器中,每个字符都是一个对象,通过享元模式共享字符对象,减少内存消耗。
  2. 图形系统: 在图形系统中,大量相似的图形对象可以通过享元模式共享,例如树木、建筑物等。
  3. 缓存: 使用享元模式实现对象缓存,避免重复创建相同的对象。
  4. 游戏开发: 在游戏开发中,使用享元模式共享相同类型的游戏对象,例如敌人、子弹等,减少内存使用。

总结

  • 面对对象很好的解决了抽象性的问题,但是作为一个运行在机器中的程序实体我们需要考虑对象的代价问题。享元模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
  • 享元模式采用对象共享的方法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实践方面要注意对象状态的处理。
  • 对象的数量太大,从而导致对象内存开销加大,什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能评空臆断。

优点

  1. 减少内存消耗: 通过共享细粒度对象,享元模式大大减少了内存的使用。当有大量相似对象需要创建时,享元模式特别有效。
  2. 提升性能: 由于减少了内存使用,享元模式可以提升系统的性能,特别是在内存有限或系统资源紧张的情况下。
  3. 分离内部状态和外部状态: 享元模式将对象的状态分为内部状态(共享部分)和外部状态(非共享部分),使得对象更加轻量化。

缺点

  1. 复杂性增加: 享元模式引入了额外的复杂性,特别是在处理对象状态时,需要明确区分内部状态和外部状态。
  2. 维护困难: 享元模式需要维护一个共享对象的池,这增加了代码的复杂性和维护难度。
  3. 线程安全问题: 在多线程环境下,需要确保享元对象的线程安全性,可能需要引入额外的同步机制,影响性能。

使用享元模式的注意事项

  1. 区分内部状态和外部状态: 在使用享元模式时,需要明确区分哪些状态可以共享(内部状态),哪些状态是对象独有的(外部状态)。
  2. 适用场景: 享元模式适用于有大量相似对象的场景,例如图形系统、文本处理、游戏开发等。如果对象数量不多,或者对象之间差异较大,使用享元模式的意义不大。
  3. 线程安全: 在多线程环境下,共享的享元对象需要是线程安全的。可以使用锁(例如std::mutex)或者其他同步机制确保线程安全。
  4. 内存泄漏: 享元模式中的享元工厂负责管理共享对象,需要确保及时释放不再使用的共享对象,以避免内存泄漏。
  5. 性能权衡: 虽然享元模式可以减少内存使用,但也会引入一些性能开销,例如对象池的维护、同步机制的使用等。在设计时需要权衡这些开销。

相关文章:

设计模式14-享元模式

设计模式14-享元模式 由来动机定义与结构代码推导特点享元模式的应用总结优点缺点使用享元模式的注意事项 由来动机 在很多应用中&#xff0c;可能会创建大量相似对象&#xff0c;例如在文字处理器中每个字符对象。在这些场景下&#xff0c;如果每个对象都独立存在&#xff0c…...

Javascript中canvas与svg详解

Canvas 在JavaScript中&#xff0c;<canvas> 元素用于在网页上绘制图形&#xff0c;如线条、圆形、矩形、图像等。它是一个通过JavaScript和HTML的<canvas>元素来工作的绘图表面。<canvas> 元素自身并不具备绘图能力&#xff0c;它仅仅提供了一个绘图环境&a…...

【BUG】已解决:No Python at ‘C:Users…Python Python39python. exe’

No Python at ‘C:Users…Python Python39python. exe’ 目录 No Python at ‘C:Users…Python Python39python. exe’ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班…...

Flink SQL 的工作机制

前言 Flink SQL 引擎的工作流总结如图所示。 从图中可以看出&#xff0c;一段查询 SQL / 使用TableAPI 编写的程序&#xff08;以下简称 TableAPI 代码&#xff09;从输入到编译为可执行的 JobGraph 主要经历如下几个阶段&#xff1a; 将 SQL文本 / TableAPI 代码转化为逻辑执…...

[AI Mem0] 源码解读,带你了解 Mem0 的实现

Mem0 的 CRUD 到底是如何实现的&#xff1f;我们来看下源码。 使用 先来看下&#xff0c;如何使用 Mem0 import os os.environ["OPENAI_API_KEY"] "sk-xxx"from mem0 import Memorym Memory()# 1. Add: Store a memory from any unstructured text re…...

【LLM】-10-部署llama-3-chinese-8b-instruct-v3 大模型

目录 1、模型下载 2、下载项目代码 3、启动模型 4、模型调用 4.1、completion接口 4.2、聊天&#xff08;chat completion&#xff09; 4.3、多轮对话 4.4、文本嵌入向量 5、Java代码实现调用 由于在【LLM】-09-搭建问答系统-对输入Prompt检查-CSDN博客 关于提示词注入…...

C语言 之 理解指针(4)

文章目录 1. 字符指针变量2. 数组指针变量2.1 对数组指针变量的理解2.2 数组指针变量的初始化 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用 5. 函数指针数组 1. 字符指针变量 我们在前面使用的主要是整形指针变量&#xff0c;现在要学…...

Java设计模式—单例模式(Singleton Pattern)

目录 一、定义 二、应用场景 三、具体实现 示例一 示例二 四、懒汉与饿汉 饿汉模式 懒汉模式 五、总结 六、说明 一、定义 二、应用场景 ‌单例模式的应用场景主要包括以下几个方面&#xff1a; ‌日志系统&#xff1a;在应用程序中&#xff0c;通常只需要一个日…...

AV1帧间预测(二):运动补偿

运动补偿(Motion Compensation,MC)是帧间预测最基础的工具&#xff0c;AV1支持两种运动补偿方式&#xff0c;一种是传统的平移运动补偿&#xff0c;另一种是仿射运动补偿。下面分别介绍这两种运动补偿方法。 平移运动补偿 平移运动补偿是最传统的运动补偿方式&#xff0c;H.26…...

数学建模(5)——逻辑回归

一、二分类 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklea…...

【C++高阶】:深入探索C++11

✨ 心似白云常自在&#xff0c;意如流水任东西 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f4…...

6. 自定义Docker镜像

如何自定义Docker镜像&#xff1a;从基础到实践 Docker作为一个容器化平台&#xff0c;使得应用的打包、分发和运行变得更加高效和便捷。本文将详细介绍如何自定义一个Docker镜像&#xff0c;包括镜像的构成、分层原理、创建自定义镜像的具体步骤&#xff0c;并演示如何打包和…...

「12月·长沙」人工智能与网络安全国际学术会议(ISAICS 2024)

人工智能与网络安全国际学术会议(ISAICS 2024)将于2024年12月20日-2024年12月22日在湖南长沙召开。会议中发表的文章将会被收录,并于见刊后提交EI核心索引。会议旨在在为国内与国际学者搭建交流平台,推进不同学科领域的融合发展&#xff0c;就当今人工智能与网络安全范畴内各学…...

【技术支持案例】使用S32K144+NSD8381驱动电子膨胀阀

文章目录 1. 前言2. 问题描述3. 理论分析3.1 NSD8381如何连接电机3.2 S32K144和NSD8381的软件配置 4.测试验证4.1 测试环境4.2 测试效果4.3 测试记录 1. 前言 最近有客户在使用S32K144NSD8381驱动电子膨胀阀时&#xff0c;遇到无法正常驱动电子膨胀阀的情况。因为笔者也是刚开…...

第二期:集成电路(IC)——智能世界的微观建筑大师

嘿&#xff0c;小伙伴们&#xff01;&#x1f44b; 我是你们的老朋友小竹笋&#xff0c;一名热爱创作和技术的工程师。上一期我们聊了聊AI芯片&#xff0c;这次我们要深入到更微观的层面&#xff0c;来探究集成电路&#xff08;IC&#xff09;的世界。准备好一起探索了吗&#…...

基于物联网的区块链算力网络,IGP/BGP协议

目录 基于物联网的区块链算力网络 IGP/BGP协议 IGP(内部网关协议) BGP(边界网关协议) 内部使用ISP的外部使用BGP的原因 一、网络规模和复杂性 二、路由协议的特性 三、满足业务需求 四、结论 基于物联网的区块链算力网络 通 过 多个物联网传感器将本地计算…...

每日一题~960 div2 A+B+C(简单奇偶博弈,构造,观察性质算贡献)

A题意&#xff1a; N 长的数组。 一次操作&#xff1a; 最开始的mx 为零。 选出一个数&#xff08;使得这个数>mx) ,之后将mx 更新为这个数&#xff0c;将这个数置为零。 不能做这个操作的&#xff0c;输。 问是否有先手赢的策略。有的话&#xff0c;输出yes 否则no 当时一…...

音视频入门基础:H.264专题(17)——FFmpeg源码获取H.264裸流文件信息(视频压缩编码格式、色彩格式、视频分辨率、帧率)的总流程

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…...

Aboboo一些操作

常用快捷键⌨ 快捷键/操作方式 功能 鼠标中键/Esc 进入/退出全屏 空格/Tab 暂停/恢复播放 左/右箭头 快退/快进 Ctrl-左/右箭头 30秒快退/快进 Alt-左/右箭头 60秒快退/快进 Ctrl-Alt-左/右箭头 播放速率调节 PageUp/PageDown 上一句/下一句 上下箭头/滚轮 …...

获取行号LineNumberReader

(每日持续更新&#xff09;jdk api之LineNumberReader基础、应用、实战-CSDN博客...

大多数团队不是“用不好 PPO”,而是“用错了 PPO”

更多时候&#xff0c;你会听到的是&#xff1a; “PPO 太复杂了&#xff0c;算了”“调了一轮&#xff0c;模型变怪了”“感觉不如再多搞点 SFT 数据” 于是 PPO 很容易被贴上一个标签&#xff1a; “理论上很强&#xff0c;工程上很坑。” 但这个结论&#xff0c;其实并不公…...

[特殊字符] GLM-4V-9B企业级方案:客户上传截图问题自动诊断

GLM-4V-9B企业级方案&#xff1a;客户上传截图问题自动诊断 1. 引言 想象一下这个场景&#xff1a;你是一家SaaS公司的技术支持工程师&#xff0c;每天的工作就是处理海量的客户工单。其中&#xff0c;有相当一部分问题描述是模糊的&#xff0c;比如“我的页面显示不正常”、…...

AirPods Pro 3 与 Bose QC Ultra Earbuds 2:无线耳机市场的激烈较量

AirPods Pro 3 与 Bose QC Ultra Earbuds 2&#xff1a;新功能大比拼最新款的 AirPods Pro 3 引入了一系列新功能&#xff0c;提升了音频效果&#xff0c;增强了降噪能力&#xff0c;还具备助听模式、实时翻译、自动切换、空间音频、心率监测等附加功能。而 Bose QuietComfort …...

WinDiskWriter:突破限制的macOS Windows启动盘制作工具

WinDiskWriter&#xff1a;突破限制的macOS Windows启动盘制作工具 【免费下载链接】windiskwriter &#x1f5a5; Windows Bootable USB creator for macOS. &#x1f6e0; Patches Windows 11 to bypass TPM and Secure Boot requirements. &#x1f47e; UEFI & Legacy …...

2026年AI就业风口!这5个神仙岗位,高薪低门槛,普通人也能转行!

根据LinkedIn数据&#xff0c;2026年AI相关岗位增长迅猛&#xff0c;其中AI咨询顾问、机器学习工程师、AI产品经理、数据与检索工程师等岗位需求旺盛&#xff0c;且部分岗位对计算机科学学位要求不高。文章详细介绍了这5个岗位的火热原因、转行路径及薪资范围&#xff0c;并给出…...

千问3.5-2B实战案例:直播截图实时分析→商品链接提取→竞品价格对比→话术生成

千问3.5-2B实战案例&#xff1a;直播截图实时分析→商品链接提取→竞品价格对比→话术生成 1. 项目背景与价值 在电商直播场景中&#xff0c;运营团队面临三个核心痛点&#xff1a; 直播过程中无法实时监测竞品价格动态人工记录商品信息效率低下且容易出错话术调整滞后于市场…...

实战复盘:从帕鲁杯应急响应赛题看企业级安全事件调查全流程

企业级安全事件调查实战指南&#xff1a;从CTF赛题到真实攻防溯源 在网络安全领域&#xff0c;应急响应能力直接决定了企业遭受攻击后的损失程度。去年某大型电商平台因未能及时识别攻击链&#xff0c;导致用户数据持续泄露长达三周&#xff0c;最终造成数亿元的直接损失。这类…...

PyTorch 2.8镜像工业设计:CAD图纸→AI生成产品渲染视频→营销素材输出

PyTorch 2.8镜像工业设计&#xff1a;CAD图纸→AI生成产品渲染视频→营销素材输出 1. 工业设计新范式&#xff1a;从CAD到营销视频的全流程AI化 传统工业设计流程中&#xff0c;从CAD图纸到产品营销素材的转化往往需要耗费大量时间和人力成本。设计师需要先完成3D建模&#x…...

【技术解析】SimpleNet:用极简网络架构革新工业图像异常检测

1. 工业图像异常检测的现状与挑战 工业生产线上的质检环节一直是个让人头疼的问题。想象一下&#xff0c;你站在一条每分钟生产上百件产品的流水线旁&#xff0c;需要肉眼检查每个产品表面是否有划痕、凹陷或污渍——这几乎是不可能完成的任务。传统计算机视觉方法在这个领域已…...

Apache Flink Agents 0.2.1版本发布,亮点几何?

Apache Flink社区宣布发布 Apache Flink Agents 0.2 系列的首个缺陷修复版本 0.2.1&#xff0c;包含3项缺陷和漏洞修复及小幅改进&#xff0c;还基于此构建了演示项目。版本发布情况Apache Flink社区很高兴地推出了 Apache Flink Agents 0.2.1 版本。此版本是 0.2 系列的首个缺…...