新闻中心

c++如何实现一个享元模式_c++结构型设计模式Flyweight【性能优化】

2025-12-13
浏览次数:
返回列表
享元模式通过共享内在状态、分离外在状态来减少内存占用;核心是用工厂缓存并复用相同内在状态的对象,客户端传入外在状态调用行为。

c++如何实现一个享元模式_c++结构型设计模式flyweight【性能优化】

享元模式(Flyweight)在 C++ 中主要用于减少内存占用,通过共享大量细粒度对象来提升性能,特别适用于对象数量庞大、状态可分“内在”与“外在”的场景(比如文字编辑器中的字符、游戏中的子弹、GUI 中的图标等)。

核心思想:分离内在状态与外在状态

内在状态(Intrinsic State)是共享的、不可变的,属于享元对象自身,比如字符的字体、大小、颜色(若统一);
外在状态(Extrinsic State)是不共享的、变化的,由客户端维护并传入,比如字符在文档中的位置、行号、是否选中等。

关键不是“把对象变少”,而是“避免重复创建相同内在状态的对象”。

手动实现享元工厂(推荐初学理解)

std::mapstd::unordered_map 缓存已创建的享元实例,按内在状态作 key 查找复用:

  • 定义享元基类(接口或抽象类),声明操作函数,参数接收外在状态
  • 派生具体享元类,只保存内在状态(const 成员),实现逻辑
  • 实现享元工厂类,负责创建/获取享元,内部用 map 管理生命周期(注意线程安全需加锁)
  • 客户端不再 new 具体类,而是调用工厂 getFlyweight(intrinsicKey),再传 extrinsic 参数调用其方法

示例关键片段:

Figma Figma

Figma 是一款基于云端的 UI 设计工具,可以在线进行产品原型、设计、评审、交付等工作。

Figma 1371 查看详情 Figma
class CharacterFlyweight {
public:
    virtual void render(int x, int y) const = 0; // 外在状态:坐标
    virtual ~CharacterFlyweight() = default;
};

class ConcreteChar : public CharacterFlyweight {
    const char ch_;
    const std::string font_;
    const int size_;
public:
    ConcreteChar(char c, std::string f, int s) 
        : ch_(c), font_(std::move(f)), size_(s) {}
    
    void render(int x, int y) const override {
        std::cout << "Draw '" << ch_ << "' at (" << x << "," << y << ") "
                  << "with " << font_ << " " << size_ << "pt\n";
    }
};

class FlyweightFactory {
    std::unordered_map<std::string, std::unique_ptr<CharacterFlyweight>> pool;
public:
    CharacterFlyweight& getFlyweight(const std::string& key) {
        auto it = pool.find(key);
        if (it != pool.end()) return *it->second;
        
        // 解析 key(如 "A|Arial|12")→ 构造对象
        auto pos1 = key.find('|'), pos2 = key.find('|', pos1+1);
        char c = key[0];
        std::string font = key.substr(pos1+1, pos2-pos1-1);
        int size = std::stoi(key.substr(pos2+1));
        
        pool[key] = std::make_unique<ConcreteChar>(c, font, size);
        return *pool[key];
    }
};

使用智能指针 + 工厂封装(更现代、安全)

避免裸指针和手动管理,用 std::shared_ptr 管理享元生命周期,工厂返回 const 引用或 shared_ptr:

  • 享元类建议设计为轻量、无状态修改(所有成员 const 或 immutable)
  • 工厂内部用 static 局部变量 + unordered_map 实现单例式缓存,天然线程安全(C++11 起)
  • 客户端拿到的是共享指针,无需关心释放;也可返回 const CharacterFlyweight& 提高性能(但需确保工厂生命周期长于使用者)

什么时候不该用享元?

享元不是银弹,滥用反而降低可读性和性能:

  • 对象总数很少(
  • 内在状态组合爆炸(比如 10 种字体 × 5 种大小 × 20 种颜色 → 1000 种 key),缓存反而吃内存
  • 外在状态传递复杂,导致接口臃肿、调用频繁出错
  • 对象本身已很轻量(如仅含一个 int),共享意义不大

基本上就这些。享元本质是空间换时间 + 状态解耦,C++ 实现关键在于明确区分内外状态、合理设计 key、用好容器和智能指针。不复杂但容易忽略外在状态的归属和线程安全性。

以上就是c++++如何实现一个享元模式_c++结构型设计模式Flyweight【性能优化】的详细内容,更多请关注其它相关文章!


# 享元模式  # c++  # 的是  # 复用  # 尼克  # 行号  # 如何实现  # 客户端  # 如何使用  # red  # 内存占用  # 靖江网站优化靠谱吗  # 安达网站建设网络推广  # SEO研究生书包推荐  # seo平台皆选6火星  # 桥西区网站制作方法优化  # 南通标题优化seo  # 海口关键词排名优化费用  # 建设部网站分享歌单  # 女团推广视频素材网站  # 拉萨拼多多seo  # 适用于  # 什么时候  # 头文件 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 我的世界mc.js免费游戏直接能玩 我的世界mc.js小游戏免费秒玩入口  Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南  windows10怎么查看硬盘序列号_windows10硬盘id查询命令  Win10系统服务哪些可以禁用 Win10安全优化服务列表【干货】  提升Kafka消费者健壮性:会话超时处理与消息处理语义  Flexbox布局实践:实现粘性导航栏与底部固定页脚  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  如何在Promise链中有效终止错误处理后的执行  Composer如何解决json扩展缺失的错误  AO3最新入口2025公告_AO3中文官网合集  Adobe PDF表单中利用J*aScript解析与格式化日期组件的教程  win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】  理解J*aScript Promise的微任务队列与执行顺序  2025年云电脑操作系统体验 | 无需本地硬件,随时随地使用高性能PC  CSS子选择器:如何区分并样式化嵌套列表的子层级  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  J*a应用集成GitHub CLI与API认证指南  《刺客信条:影》PS5 Pro和Switch 2画面对比  抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩  Fabric模组开发:自定义物品与物品组的现代管理方法  win11 Snap Layouts怎么用 Win11窗口布局与分屏多任务高效指南【必学】  搜狗浏览器如何使用密码生成器创建强密码 搜狗浏览器内置密码安全工具  QQ邮箱网页版快速登录 QQ邮箱邮箱账号官方入口地址  WordPress插件开发:正确注册卸载钩子与避免常见陷阱  蛙漫画网页版全站入口 蛙漫热门作品免费浏览  谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问  移动端XML文件怎么转换成Excel 手机和平板上的解决方案  excel怎么制作工资条 excel快速生成工资条的方法  poki网页游戏推荐_poki免费游戏平台入口  Go语言中JSON数据解码与字段访问指南  解决 Express.js 中 PUT 请求密码修改失败的路由配置指南  抖音创作助手登录入口_抖音创作辅助工具官网直达  海棠电脑版入口_通过电脑访问海棠官网阅读  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  如何有效阻止外部脚本意外修改内联样式的高度属性  Excel中VLOOKUP的第四个参数是干什么用的_Excel VLOOKUP第四参数作用解析  蛙漫官方正版入口 蛙漫网页在线全集免费观看  Win10如何清理注册表垃圾 Win10手动清理无效注册表【技巧】  小米汽车11月交付量突破40000台!雷军:将继续努力  最新韩小圈网页版登录入口_官网在线观看官方链接  J*a实现学校排课程序_面向对象结构化项目示例  护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】  动漫花园资源网使用步骤_动漫花园资源网下载流程  c++中的std::launder有什么实际用途_c++对象生命周期与指针优化  微博网页版主页入口 微博官方网站免登录访问  php源码怎么在电脑上测试_电脑测试php源码方法步骤【教程】  处理动态列数据:J*a ArrayList的正确初始化与字符累加教程  React中useState与局部变量:理解组件状态管理与渲染机制  12306选座如何查看座位示意图_12306座位示意图解读与使用 

搜索