08.C++设计模式-享元模式

1. 模式定义

享元模式(Flyweight Pattern)是一种结构型设计模式,通过共享大量细粒度对象来减少内存占用。它将对象的状态分为内在状态 (可共享)和外在状态(不可共享)。

2. 核心角色

  • Flyweight:享元接口,声明接收外在状态的方法
  • ConcreteFlyweight:具体享元,存储内在状态
  • FlyweightFactory:工厂类,创建并管理享元对象
  • Client:客户端,维护外在状态

3. 逻辑结构图

<<interface>>
Flyweight
+operation(extrinsicState)
ConcreteFlyweight
-intrinsicState
+operation(extrinsicState)
FlyweightFactory
-flyweights: map
+getFlyweight(key)
Client
-extrinsicState
+main()

4. 应用场景

  • 文本编辑器:共享字符对象(每个字符的字体、大小等属性)
  • 图形系统:重复使用的图形元素(如游戏中的子弹、地图瓦片)
  • 数据库连接池:共享数据库连接
  • 字符串常量池:Java/C#中的字符串驻留
  • 缓存系统:重复使用的计算结果

5. C++代码示例

cpp 复制代码
#include <iostream>
#include <unordered_map>
#include <memory>
#include <string>

// 享元接口
class Character {
public:
    virtual ~Character() = default;
    virtual void display(int fontSize, const std::string& color) = 0;
};

// 具体享元:字符对象
class ConcreteCharacter : public Character {
private:
    char symbol;  // 内在状态(共享)
    
public:
    ConcreteCharacter(char c) : symbol(c) {}
    
    void display(int fontSize, const std::string& color) override {
        std::cout << "字符: " << symbol 
                  << ", 字体大小: " << fontSize 
                  << ", 颜色: " << color << std::endl;
    }
};

// 享元工厂
class CharacterFactory {
private:
    std::unordered_map<char, std::shared_ptr<Character>> characters;
    
public:
    std::shared_ptr<Character> getCharacter(char key) {
        auto it = characters.find(key);
        if (it != characters.end()) {
            return it->second;
        }
        
        auto newChar = std::make_shared<ConcreteCharacter>(key);
        characters[key] = newChar;
        std::cout << "创建新字符: " << key << std::endl;
        return newChar;
    }
    
    size_t getSize() const {
        return characters.size();
    }
};

// 客户端代码
int main() {
    CharacterFactory factory;
    
    // 创建文本 "Hello" 但只共享字符对象
    std::string text = "Hello";
    std::vector<std::pair<char, std::pair<int, std::string>>> textWithStyle = {
        {'H', {12, "Red"}}, {'e', {12, "Black"}}, {'l', {12, "Black"}},
        {'l', {14, "Blue"}}, {'o', {12, "Black"}}
    };
    
    // 渲染文本
    for (const auto& [ch, style] : textWithStyle) {
        auto character = factory.getCharacter(ch);
        character->display(style.first, style.second);
    }
    
    std::cout << "\n实际创建的字符对象数量: " << factory.getSize() << std::endl;
    // 输出: 实际创建的字符对象数量: 4 (H, e, l, o)
    // 'l' 被重用,没有重复创建
    
    return 0;
}

6. 内存优化效果图

享元模式 - 共享字符对象
传统方式 - 每个位置独立对象
字符H对象1
字符e对象2
字符l对象3
字符l对象4
字符o对象5
字符H对象
字符e对象
字符l对象
字符o对象
位置3引用
位置4引用

7. 关键要点

方面 说明
优势 减少内存占用;提高性能(对象复用);分离内/外在状态
劣势 增加系统复杂度;需要分离状态;线程安全问题
适用条件 大量重复对象;对象大部分状态可外部化;对象可分组共享

8. 最佳实践

cpp 复制代码
// 线程安全的享元工厂
class ThreadSafeCharacterFactory {
private:
    std::unordered_map<char, std::shared_ptr<Character>> characters;
    std::mutex mtx;
    
public:
    std::shared_ptr<Character> getCharacter(char key) {
        std::lock_guard<std::mutex> lock(mtx);
        auto it = characters.find(key);
        if (it != characters.end()) {
            return it->second;
        }
        auto newChar = std::make_shared<ConcreteCharacter>(key);
        characters[key] = newChar;
        return newChar;
    }
};

享元模式特别适合处理大量细粒度对象的场景,通过共享技术有效降低内存消耗,是性能优化的重要工具。

相关推荐
一木 之林2 小时前
四、STL容器与数据结构
开发语言·数据结构·c++
程与留3 小时前
07_QMainWindow 与应用程序框架——菜单栏、工具栏、状态栏
c++·qt
_Narcissus_4 小时前
二分算法笔记及例题
数据结构·c++·笔记·算法·蓝桥杯·查找·二分算法
阿无,4 小时前
设计模式之责任链模式
设计模式·责任链模式
青少儿编程课堂6 小时前
用图形化编程做一个“少年探险闯关”小游戏:方向键控制、碰撞检测与多关卡串起完整项目
c++·python·算法·bfs·信息学竞赛
liulilittle6 小时前
长上下文的成本结构与「甜点区间」——从推理引擎的物理约束看 200K/256K/400K
c++·人工智能·ai·llm·注意力·qkv
十五年专注C++开发6 小时前
100w条数据丝滑滚动!Qt Model/View 架构实战(二)
开发语言·c++·qt
skr爱码士7 小时前
06_Qt 常用数据类型与容器:QString、QList、QVector、QMap 的性能与实现分析
开发语言·c++·qt
奶茶树7 小时前
【C++】13. C++11新特性【上】
c语言·开发语言·c++·git·github
wabs6668 小时前
关于栈【力扣1047. 删除字符串中的所有相邻重复项的思考】
数据结构·c++·算法·leetcode··代码随想录