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 小时前
C++ Boost库【4】 --分词器的使用
c++·windows·microsoft
码农-阿杰2 小时前
Java 线程中断机制深度解析:从 API 到底层 C++ 实现
java·开发语言·c++
Brilliantwxx2 小时前
【C++】priority_queue以及 仿函数 的学习
开发语言·c++·笔记·学习·算法
宠..2 小时前
VS Code 修改 C++ 标准同时修改错误检测标准
java·linux·开发语言·javascript·c++·python·qt
wuyoula2 小时前
如何在捷云鲸论坛高效获取高质量技术解答?
服务器·c++·人工智能·tcp/ip·源码
.YM.Z2 小时前
C++类和对象(中)
c++·类和对象
Tairitsu_H2 小时前
C++:优先队列的模拟实现
开发语言·c++·stl·优先队列
lzh200409193 小时前
效率与安全并重:C++ 线程安全
linux·c++
Shan12053 小时前
RAII妙用:使用标准库的包装器
开发语言·c++