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;
    }
};

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

相关推荐
anew___8 小时前
蜂鸣器播放音乐——让 Arduino 唱出旋律
c++·stm32·单片机·嵌入式硬件·c
stolentime10 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法
tdtsmt10 小时前
穿戴硬件量产工艺实录:天地通电子智能手表主板 SMT 贴片案
c++
m0_7345717614 小时前
深入理解C++ 析构函数<一>基本概念
开发语言·c++
t-think15 小时前
C++ string 类(上)—— string类初识与常用接口详解
开发语言·c++
cpp_learners15 小时前
C++ 实现责任链模式(Chain of Responsibility):从一堆 if-else 到可插拔的处理管道
开发语言·c++·责任链模式
YHL15 小时前
🎯 JavaScript 单例模式(Singleton Pattern)—— 从理论到实战
javascript·设计模式
郝学胜_神的一滴15 小时前
C++11 工程级应用 12:编译期类型魔法,干掉重复与臃肿的代码
c++·visual studio
David猪大卫17 小时前
【C++修炼】哈希表的实现
数据结构·c++·笔记·学习·算法·哈希算法·散列表
广州山泉婚姻17 小时前
列表初始化:C++11全新初始化体系
c++·人工智能