享元模式通过共享减少对象数量,c++中利用工厂和容器管理内部状态相同的对象,结合不可变设计与智能指针优化内存使用,适用于高频创建相似对象的场景。

享元模式(Flyweight Pattern)是一种结构型设计模式,它的核心思想是通过共享技术来支持大量细粒度对象的复用,从而减少内存中对象的数量,降低系统开销。在C++中,尤其适用于创建大量相似对象的场景,比如文本编辑器中的字符格式、游戏开发中的子弹或敌人类型等。
享元模式的核心概念
享元模式将对象的状态分为两类:
- 内部状态(Intrinsic State):可以被共享,不会随环境改变,通常作为享元对象的成员变量。
- 外部状态(Extrinsic State):依赖于上下文,不可共享,使用时由客户端传入。
通过分离这两类状态,多个上下文可以共享同一个享元对象,只需传入不同的外部状态即可表现出不同行为。
实现一个简单的享元工厂
在C++中,通常借助一个工厂类来管理享元对象的创建和共享。工厂维护一个已创建享元的容器(如map),避免重复创建相同内部状态的对象。
立即学习“C++免费学习笔记(深入)”;
#include <iostream>
#include <map>
#include <string>
<p>// 享元接口或基类
class CharacterStyle {
public:
CharacterStyle(const std::string& font, int size, const std::string& color)
: font<em>(font), size</em>(size), color_(color) {}</p><pre class='brush:php;toolbar:false;'>void display(const std::string& content) const {
std::cout << "Text: " << content
<< " | Font: " << font_
<< ", Size: " << size_
<< ", Color: " << color_ << std::endl;
}private: std::string font; int size; std::string color_; };
// 享元工厂 class StyleFactory { public: CharacterStyle* getStyle(const std::string& font, int size, const std::string& color) { std::string key = font + "-" + std::to_string(size) + "-" + color;
if (styles.find(key) == styles.end()) {
styles[key] = new CharacterStyle(font, size, color);
}
return styles[key];
}
~StyleFactory() {
for (auto& pair : styles) {
delete pair.second;
}
}private: std::map<:string characterstyle> styles; };
上面代码中,CharacterStyle 表示字体样式,其内部状态是字体、大小和颜色。工厂通过组合这些属性生成唯一键,确保相同样式的对象只创建一次。
客户端使用示例
客户端通过工厂获取享元对象,并传入外部状态(如具体显示的文本内容)来使用。
int main() {
StyleFactory factory;
<pre class='brush:php;toolbar:false;'>// 模拟文档中有多个字符,但只有几种样式
CharacterStyle* style1 = factory.getStyle("Arial", 12, "black");
CharacterStyle* style2 = factory.getStyle("Times New Roman", 14, "red");
CharacterStyle* style3 = factory.getStyle("Arial", 12, "black"); // 应该复用 style1
style1->display("Hello");
style2->display("World");
style3->display("!");
// 验证是否为同一对象
std::cout << "style1 == style3: " << (style1 == style3 ? "true" : "false") << std::endl;
return 0;}
输出结果会显示,尽管请求了两次相同的样式,但实际返回的是同一个对象指针,有效减少了内存占用。
注意事项与优化建议
- 享元对象应设计为不可变(immutable),以保证共享安全。一旦创建,其内部状态不应被修改。
- 工厂需管理对象生命周期,避免内存泄漏。可考虑使用智能指针(如
std::shared_ptr)替代原始指针。 - 键的生成要高效且无歧义,推荐使用字符串拼接或哈希方式。
- 并非所有对象都适合做享元。仅当对象创建频繁、内部状态高度重复时才值得引入。
基本上就这些。享元模式通过共享减少对象数量,在C++中结合工厂和容器能有效控制内存使用,特别适合资源敏感的应用场景。关键在于合理划分内外状态,确保共享的安全与高效。










