设计模式(九)--享元模式

目录

享元模式的关键组成部分

享元模式的应用场景

享元模式的实现步骤

享元模式的示例

步骤1:定义享元接口

步骤2:实现具体享元类

步骤3:实现享元工厂类

步骤4:客户端代码

运行结果

解释

享元模式的优点

享元模式的缺点

总结


享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建大量相似对象所需的内存消耗。它通过共享尽可能多的数据来达到最大化地复用细粒度的对象。享元模式适用于需要创建大量相似对象的情况,这些对象大多数是细粒度的,并且可以共享某些部分的信息。

享元模式的关键组成部分

  1. 享元接口(Flyweight):定义了所有具体享元类的公共接口。
  2. 具体享元类(Concrete Flyweights):实现享元接口,并且每个享元存储内部状态的一部分。
  3. 非享元对象(Unshared Concrete Flyweights):存储外部状态,这些状态不能共享。
  4. 享元工厂(Flyweight Factory):负责创建和管理享元对象。

享元模式的应用场景

享元模式适用于以下情况:

  • 对象的大部分状态可以外部化。
  • 许多对象的结构几乎相同,只是某些个别属性不同。
  • 由于使用了大量的细粒度对象,导致内存消耗过大。

享元模式的实现步骤

  1. 定义享元接口。
  2. 实现具体享元类。
  3. 实现享元工厂类。
  4. 使用享元工厂来获取具体的享元对象,并传递外部状态。

享元模式的示例

假设我们在开发一个绘图应用,需要绘制大量的圆圈。由于圆圈的颜色和位置可能不同,但我们希望共享尽可能多的信息,以减少内存消耗。

步骤1:定义享元接口

c

深色版本

1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5typedef struct Circle {
6    void (*draw)(struct Circle *circle, int x, int y);
7} Circle;
8
9void drawCircle(Circle *circle, int x, int y) {
10    printf("Drawing circle at (%d, %d)\n", x, y);
11}
步骤2:实现具体享元类

在这个例子中,我们将根据颜色创建不同的享元对象。颜色作为内部状态,而位置作为外部状态。

c

深色版本

1typedef struct ColorCircle {
2    Circle base;
3    char color[20];
4} ColorCircle;
5
6ColorCircle* createColorCircle(const char *color) {
7    ColorCircle *circle = (ColorCircle *)malloc(sizeof(ColorCircle));
8    strcpy(circle->color, color);
9    circle->base.draw = drawColorCircle;
10    return circle;
11}
12
13void drawColorCircle(Circle *circle, int x, int y) {
14    ColorCircle *colorCircle = (ColorCircle *)circle;
15    printf("Drawing %s circle at (%d, %d)\n", colorCircle->color, x, y);
16}
17
18void destroyColorCircle(ColorCircle *circle) {
19    free(circle);
20}
步骤3:实现享元工厂类

享元工厂负责创建和管理享元对象,并确保相同的享元对象不会被重复创建。

c

深色版本

1typedef struct CircleFactory {
2    ColorCircle *circles[100]; // 假设最多有100个不同的颜色
3    int count;
4} CircleFactory;
5
6CircleFactory* createCircleFactory() {
7    CircleFactory *factory = (CircleFactory *)malloc(sizeof(CircleFactory));
8    factory->count = 0;
9    return factory;
10}
11
12Circle* getCircle(CircleFactory *factory, const char *color) {
13    for (int i = 0; i < factory->count; ++i) {
14        if (strcmp(factory->circles[i]->color, color) == 0) {
15            return &(factory->circles[i]->base);
16        }
17    }
18
19    // 如果没有找到,则创建一个新的享元对象
20    if (factory->count < 100) {
21        factory->circles[factory->count] = createColorCircle(color);
22        factory->count++;
23        return &(factory->circles[factory->count - 1]->base);
24    }
25
26    // 如果超过最大数量,可以选择其他处理方式
27    return NULL;
28}
29
30void destroyCircleFactory(CircleFactory *factory) {
31    for (int i = 0; i < factory->count; ++i) {
32        destroyColorCircle(factory->circles[i]);
33    }
34    free(factory);
35}
步骤4:客户端代码

c

深色版本

1int main() {
2    CircleFactory *circleFactory = createCircleFactory();
3
4    Circle *redCircle = getCircle(circleFactory, "red");
5    Circle *blueCircle = getCircle(circleFactory, "blue");
6    Circle *greenCircle = getCircle(circleFactory, "green");
7
8    drawCircle(redCircle, 10, 20);
9    drawCircle(blueCircle, 30, 40);
10    drawCircle(greenCircle, 50, 60);
11
12    // 再次获取,应该返回同一个对象
13    Circle *anotherRedCircle = getCircle(circleFactory, "red");
14    drawCircle(anotherRedCircle, 70, 80);
15
16    destroyCircleFactory(circleFactory);
17
18    return 0;
19}

运行结果

当你运行上述 main 函数时,你会看到以下输出:

 

深色版本

1Drawing red circle at (10, 20)
2Drawing blue circle at (30, 40)
3Drawing green circle at (50, 60)
4Drawing red circle at (70, 80)

解释

在这个例子中,CircleFactory 负责创建和管理 ColorCircle 对象。每次调用 getCircle 方法时,工厂都会检查是否已经有对应的 ColorCircle 对象存在,如果有则直接返回,否则创建一个新的对象。通过这种方式,我们可以避免重复创建相同颜色的圆圈对象,从而节省内存。

享元模式的优点

  1. 内存优化:通过共享部分数据,可以显著减少内存消耗。
  2. 性能提升:由于减少了对象的创建,性能有所提升。
  3. 代码清晰:通过工厂模式管理享元对象,代码更加清晰。

享元模式的缺点

  1. 复杂度增加:需要额外的管理机制来确保享元对象的正确创建和共享。
  2. 外部状态管理:享元模式需要外部状态管理,这可能会增加代码的复杂度。

总结

享元模式通过共享部分数据来减少内存消耗,并且适用于需要创建大量相似对象的场景。在设计系统时,如果发现有大量的细粒度对象,并且其中有很多可以共享的部分,可以考虑使用享元模式来优化内存使用和提高性能。

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值