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

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

相关推荐
咖啡八杯1 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
博客18002 天前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝
郝学胜_神的一滴2 天前
CMake 026:属性体系精讲、四大作用域全解 & 实战代码落地
c++·cmake
众少成多积小致巨2 天前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
槑有老呆3 天前
别再手搓 Prompt 了,那个叫"手动挡循环"
设计模式
用户6919026813393 天前
Vibe Coding 开发项目的基本范式
人工智能·设计模式·代码规范
怕浪猫4 天前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构
Larcher6 天前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式