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

设计模式十一:享元模式(Flyweight Pattern)

享元模式是一种结构型设计模式,它通过共享对象来最小化内存使用或计算开销。这种模式适用于大量相似对象的情况,通过共享这些对象的公共部分来减少资源消耗。

基本概念

享元模式的核心思想是将对象的内在状态(不变的部分)和外在状态(变化的部分)分离:

  • 内在状态(Intrinsic State):存储在享元内部,可以被多个对象共享,独立于具体场景

  • 外在状态(Extrinsic State):取决于具体场景,通常由客户端保存或计算

实现示例

下面是一个简单的享元模式实现示例,模拟文本编辑器中的字符处理:

#include <iostream>
#include <string>
#include <unordered_map>// 享元类 - 表示字符及其内在状态(字体、大小等)
class Character {
public:Character(char symbol, const std::string& font, int size): symbol_(symbol), font_(font), size_(size) {}void display(int position) const {std::cout << "Character: " << symbol_ << ", Font: " << font_<< ", Size: " << size_<< ", Position: " << position << std::endl;}private:char symbol_;std::string font_;int size_;
};// 享元工厂 - 创建和管理享元对象
class CharacterFactory {
public:Character* getCharacter(char key, const std::string& font, int size) {// 使用组合键来唯一标识享元对象std::string compositeKey = std::string(1, key) + "_" + font + "_" + std::to_string(size);if (characters_.find(compositeKey) == characters_.end()) {characters_[compositeKey] = new Character(key, font, size);}return characters_[compositeKey];}~CharacterFactory() {for (auto& pair : characters_) {delete pair.second;}}private:std::unordered_map<std::string, Character*> characters_;
};// 客户端代码
int main() {CharacterFactory factory;// 文档中的字符及其位置std::string text = "Hello, World!";for (size_t i = 0; i < text.size(); ++i) {char c = text[i];// 假设所有字符使用相同的字体和大小Character* character = factory.getCharacter(c, "Arial", 12);character->display(i); // 位置是外在状态,由客户端提供}return 0;
}

UML结构 

 

享元模式的组成

  1. Flyweight(享元接口):定义享元对象的接口

  2. ConcreteFlyweight(具体享元):实现享元接口,存储内在状态

  3. UnsharedConcreteFlyweight(非共享具体享元):不需要共享的享元实现

  4. FlyweightFactory(享元工厂):创建和管理享元对象,确保合理共享

  5. Client(客户端):维护对享元的引用,计算或存储外在状态

适用场景

  • 一个应用程序使用了大量相似对象

  • 由于大量对象造成很大的存储开销

  • 对象的大多数状态可以变为外部状态

  • 移除了外部状态后,可以用较少的共享对象替代大量对象

优点

  • 减少内存使用,因为共享了相似对象

  • 减少了对象的创建数量,提高了性能

  • 将状态外部化,使得对象更轻量

缺点

  • 增加了系统复杂性,需要分离内在和外在状态

  • 可能需要线程安全考虑,因为享元对象是共享的

  • 外在状态需要由客户端维护和管理

实际应用

  • 文本编辑器中的字符处理

  • 游戏开发中的粒子系统

  • 图形编辑器中的图形对象

  • 数据库连接池

  • 任何需要大量细粒度对象的场景

在C++标准库中,std::string的写时复制(COW)实现某种程度上也使用了享元模式的思想。

http://www.dtcms.com/a/299123.html

相关文章:

  • 微信小程序 自定义带图片弹窗
  • 单机版管家婆数据库日志自动清理计划
  • 从一个“诡异“的C++程序理解状态机、防抖与系统交互
  • 原创-锐能微82xx系列电能计量芯片软件驱动开发与精度校准流程完全指南
  • 读心与芯:我们与机器人的无限未来05未来之路
  • 学习随笔录
  • Apache HTTP Server 2.4.49 的目录遍历漏洞CVE-2021-41773
  • xLua和C#交互
  • C#与C++交互开发系列(二十四):WinForms 应用中嵌入C++ 原生窗体
  • 安卓服务与多线程
  • uniapp+高德地图实现打卡签到、打卡日历
  • uniapp input 如何只读禁用输入可点击
  • ISIS GR实验案例
  • 机器学习特征工程:特征选择及在医学影像领域的应用
  • QT中启用VIM后粘贴复制快捷键失效
  • 电子电气架构 --- 车载软件交样评审流程
  • Python 数据分析(二):Matplotlib 绘图
  • Python点阵字生成与优化:从基础实现到高级渲染技术
  • P1064 [NOIP 2006 提高组] 金明的预算方案 题解
  • 主要分布在腹侧海马体(vHPC)CA1区域(vCA1)的混合调谐细胞(mixed-tuning cells)对NLP中的深层语义分析的积极影响和启示
  • LeetCode 刷题【15. 三数之和】
  • Ubuntu 18.04安装Fast-Lio2教程
  • 开发者说|RoboTransfer:几何一致视频世界模型,突破机器人操作泛化边界
  • Vue当中背景图无法占满屏幕的解决方法
  • JavaScript里的reduce
  • JavaScript 对象、字符串的统计和排序高频面试题
  • Spring Boot 3 如何整合 MinIO 实现分布式文件存储?
  • 【20】C# 窗体应用WinForm ——下拉列表框ComboBox属性、方法、实例应用
  • 掌握JavaScript函数封装与作用域
  • 【资讯】2025年软件行业发展趋势:AI驱动变革,云原生与安全成核心