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

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

相关推荐
lqqjuly1 天前
C++ 完整知识体系—从基础语法到现代 C++23 的系统性总结
c++·c++23
王老师青少年编程1 天前
信奥赛C++提高组csp-s之FHQ Treap
c++·csp·平衡树·信奥赛·csp-s·提高组·fhq treap
QiLinkOS1 天前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Irissgwe1 天前
c++STL--string类
c++·stl·string
Irissgwe1 天前
c++类型转换
c++·类型转换·explicit·static_cast·const_cast·dynamic_cast·rtti
智者知已应修善业1 天前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机
智者知已应修善业1 天前
【51单片机4位静态数码管显示1234】2023-11-14
c++·经验分享·笔记·算法·51单片机
抓虾爪1 天前
ST意法代理商粤科源兴丨LSM6DS3全系列现货库存,LSM6DS3TR-C当天可发
c++
妙为1 天前
unreal engine5.7.4,创建ThirdPerson第三人称模版,类型是c++崩溃
c++·ue5·虚幻·unreal engine5
郝学胜_神的一滴1 天前
Qt 高级开发 021:零基础吃透 QVBoxLayout 垂直布局
c++·qt