享元模式通过共享内部状态减少对象数量,降低内存开销;C++中利用工厂和哈希容器管理共享池,结合外部状态实现高效对象复用,适用于文本、图形等大量相似对象场景。

在C++中,享元模式(Flyweight Pattern)用于优化性能,特别是在需要创建大量相似对象的场景下。通过共享细粒度对象,减少内存占用和对象创建开销,从而提升程序效率。这种模式特别适用于对象中存在大量可共享的“内部状态”,而仅有少量变化的“外部状态”。
享元模式的核心思想
享元模式将对象的状态划分为两类:
- 内部状态(Intrinsic State):可以被共享,不会随环境改变,通常在享元对象创建时确定。
- 外部状态(Extrinsic State):依赖于上下文,不可共享,由客户端在调用时传入。
通过分离这两类状态,多个对象可以共享同一个内部状态实例,避免重复创建相同内容的对象。
应用场景与优化目标
常见适用场景包括:
立即学习“C++免费学习笔记(深入)”;
- 文本编辑器中字符格式对象(字体、颜色等可共享)
- 图形系统中图标或样式对象
- 游戏中大量相同类型的敌人或道具
目标是减少内存中重复对象的数量,降低构造/析构开销,提高缓存局部性。
实现方式:享元工厂与共享池
使用工厂类管理享元对象的创建和共享,确保相同内部状态只创建一次。
class CharacterStyle {
std::string font;
int size;
std::string color;
public:
CharacterStyle(const std::string& f, int s, const std::string& c)
: font(f), size(s), color(c) {}
void display() const {
std::cout << "Font: " << font << ", Size: " << size << ", Color: " << color << "\n";
}
// 支持比较,用于查找是否已存在相同样式
bool operator==(const CharacterStyle& other) const {
return font == other.font && size == other.size && color == other.color;
}};
// 用于哈希查找
struct StyleHash {
size_t operator()(const CharacterStyle& s) const {
return std::hash<:string>{}(s.font) ^
std::hash{}(s.size) ^
std::hash<:string>{}(s.color);
}
};
class StyleFlyweightFactory {
std::unordered_set pool;
public:
const CharacterStyle getStyle(const std::string& font, int size, const std::string& color) {
CharacterStyle temp(font, size, color);
auto it = pool.find(temp);
if (it != pool.end()) {
return &(it); // 返回已存在的引用
} else {
pool.emplace(temp);
auto newIt = pool.find(temp);
return &(*newIt);
}
}
};
工厂内部使用
unordered_set管理唯一实例,避免重复创建。客户端获取的是指向共享对象的指针,节省内存。
结合外部状态使用享元对象
享元对象本身不保存位置、内容等外部状态,这些由客户端在运行时传入。
class Character {
char value;
const CharacterStyle* style; // 共享的内部状态
int x, y; // 外部状态:位置
public:
Character(char val, const CharacterStyle* s, int posX, int posY)
: value(val), style(s), x(posX), y(posY) {}
void draw() const {
std::cout << "Drawing '" << value << "' at (" << x << "," << y << ") with style: ";
style->display();
}};
多个
Character对象可共享同一个
CharacterStyle,仅位置和字符值不同。
基本上就这些。享元模式通过共享减少对象数量,适合处理大量细粒度对象的场景。关键在于合理划分内外状态,并用工厂管理生命周期。C++中配合哈希容器能高效实现共享池,显著降低内存开销。









