享元模式(Flyweight Pattern)是一种用于减少对象数量从而减少内存使用的设计模式。它的核心思想是尽可能地重用已创建的对象,而不是每次需要时都创建新的实例。这种模式尤其适用于需要大量相似对象的场景,通过共享这些对象的公共状态来节省资源。
想象一个电子游戏,其中有许多不同类型的树木。每种树木可能有不同的颜色和形状,但它们的生长环境(比如土壤类型、阳光照射量等)对于所有树木来说都是相同的。如果我们为每棵树创建一个完整的对象,那么将会消耗大量的内存资源。而实际上,我们可以利用享元模式来优化这个问题。
实现步骤
#include
#include
#include
// 定义一个结构体来表示树木的内部状态
typedef struct {
char color[10];
char shape[10];
} IntrinsicState;
// 树木的抽象接口
typedef struct Tree {
IntrinsicState *state;
void (*display)(struct Tree *tree, const char *soilType);
} Tree;
// 具体的树木类型
typedef struct OakTree {
Tree base;
} OakTree;
// 具体的树木类型
typedef struct PineTree {
Tree base;
} PineTree;
// 构造函数
void oak_tree_init(OakTree *tree, IntrinsicState *state) {
tree->base.state = state;
tree->base.display = oak_tree_display;
}
void pine_tree_init(PineTree *tree, IntrinsicState *state) {
tree->base.state = state;
tree->base.display = pine_tree_display;
}
// 显示方法
void oak_tree_display(Tree *tree, const char *soilType) {
printf("Oak tree: color=%s, shape=%s, soilType=%s\n", tree->state->color, tree->state->shape, soilType);
}
void pine_tree_display(Tree *tree, const char *soilType) {
printf("Pine tree: color=%s, shape=%s, soilType=%s\n", tree->state->color, tree->state->shape, soilType);
}
// 享元工厂
typedef struct {
Tree *trees;
int count;
} FlyweightFactory;
void flyweight_factory_init(FlyweightFactory *factory) {
factory->trees = NULL;
factory->count = 0;
}
Tree *flyweight_factory_get(FlyweightFactory *factory, const char *color, const char *shape) {
IntrinsicState state = { .color = strdup(color), .shape = strdup(shape) };
for (int i = 0; i < factory->count; ++i) {
if (!strcmp(factory->trees[i].state->color, state.color) && !strcmp(factory->trees[i].state->shape, state.shape)) {
return &factory->trees[i];
}
}
// 如果不存在,则创建一个新的树木
Tree *newTree = (Tree *)malloc(sizeof(Tree));
OakTree *oak = (OakTree *)malloc(sizeof(OakTree));
oak_tree_init(oak, &state);
newTree = &oak->base;
factory->trees = realloc(factory->trees, (factory->count + 1) * sizeof(Tree));
factory->trees[factory->count++] = *newTree;
return newTree;
}
int main() {
FlyweightFactory factory;
flyweight_factory_init(&factory);
Tree *tree1 = flyweight_factory_get(&factory, "green", "round");
Tree *tree2 = flyweight_factory_get(&factory, "brown", "tall");
Tree *tree3 = flyweight_factory_get(&factory, "green", "round"); // 应该与tree1共享
tree1->display(tree1, "sand");
tree2->display(tree2, "clay");
tree3->display(tree3, "sand");
free(factory.trees);
return 0;
}
IntrinsicState
结构体来存储树木的固有属性,如颜色和形状。Tree
是一个抽象接口,它有一个 display
方法用来显示树木的信息。OakTree
和 PineTree
分别实现了 Tree
接口。FlyweightFactory
负责管理所有树木的实例,并确保具有相同固有状态的树木共享同一个实例。Oak tree: color=green, shape=round, soilType=sand
Pine tree: color=brown, shape=tall, soilType=clay
Oak tree: color=green, shape=round, soilType=sand
创建树木实例
main()
函数中,我们初始化了一个 FlyweightFactory
对象 factory
。flyweight_factory_get()
函数三次来尝试获取不同的树木实例:
"green"
, "round"
)."brown"
, "tall"
)."green"
, "round"
).共享实例
输出
当执行 display
方法时,程序将输出每棵树的具体信息,包括颜色、形状以及土壤类型。
这里可以看到,第三次输出与第一次完全相同,这是因为两次请求的是同一棵绿色圆形的橡树。这表明我们成功实现了享元模式,相同的树木实例被共享了。
享元模式是一种旨在减少对象数量从而降低内存使用量的设计模式。它通过共享对象的公共状态来实现这一目标,特别适合于需要大量相似对象的场景。
关键点
适用场景
优点
缺点
实现注意事项