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