当前位置: 首页 > article >正文

C++实现设计模式---享元模式 (Flyweight)

享元模式 (Flyweight)

享元模式 是一种结构型设计模式,它通过共享对象来减少内存使用和对象创建的开销。当系统中有大量相似对象时,享元模式可以避免重复创建相同对象,从而节省内存。


意图

  • 通过共享相同对象来减少内存消耗。
  • 用于系统中存在大量相似对象的场景。

使用场景

  1. 大量相似对象

    • 系统中存在许多共享的对象,这些对象的状态大部分是相同的。
  2. 状态可以分为内部状态和外部状态

    • 内部状态:可以被共享的部分,不会随上下文变化。
    • 外部状态:特定于场景的部分,不可共享,需要由客户端管理。
  3. 节约内存

    • 系统需要大量创建对象,但内存开销成为瓶颈。

参与者角色

  1. 享元接口 (Flyweight)

    • 定义共享对象的公共接口。
  2. 具体享元 (ConcreteFlyweight)

    • 实现享元接口,存储可以共享的内部状态。
  3. 非共享享元 (UnsharedFlyweight)

    • 不可以共享的子类,通常会组合共享的享元对象。
  4. 享元工厂 (FlyweightFactory)

    • 创建并管理享元对象,确保共享对象的唯一性。
  5. 客户端 (Client)

    • 负责管理外部状态,并将外部状态与享元对象结合使用。

示例代码

以下代码展示了如何使用享元模式来共享图形对象,例如圆形。

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>

// 享元接口:图形
class Shape {
public:
    virtual ~Shape() = default;
    virtual void draw(const std::string& color) const = 0; // 外部状态为颜色
};

// 具体享元类:圆形
class Circle : public Shape {
private:
    int radius; // 内部状态:半径

public:
    Circle(int r) : radius(r) {}

    void draw(const std::string& color) const override {
        std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;
    }
};

// 享元工厂:管理享元对象
class ShapeFactory {
private:
    std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象

public:
    std::shared_ptr<Shape> getCircle(int radius) {
        if (shapes.find(radius) == shapes.end()) {
            shapes[radius] = std::make_shared<Circle>(radius);
            std::cout << "Creating a circle with radius " << radius << std::endl;
        }
        return shapes[radius];
    }
};


// 客户端代码
int main() {
    ShapeFactory factory;

    // 获取共享的圆形对象
    auto circle1 = factory.getCircle(5);
    auto circle2 = factory.getCircle(10);
    auto circle3 = factory.getCircle(5); // 共享对象

    // 使用享元对象绘制
    circle1->draw("red");   // 外部状态:红色
    circle2->draw("blue");  // 外部状态:蓝色
    circle3->draw("green"); // 外部状态:绿色

    return 0;
}

代码解析

1. 享元接口 (Shape)
  • 定义了 draw 方法,用于绘制图形,并接收外部状态作为参数:
class Shape {
public:
    virtual ~Shape() = default;
    virtual void draw(const std::string& color) const = 0;
};
2. 具体享元类 (Circle)
  • 实现了 Shape 接口,存储可以共享的内部状态(如半径):
class Circle : public Shape {
private:
    int radius; // 内部状态

public:
    Circle(int r) : radius(r) {}

    void draw(const std::string& color) const override {
        std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;
    }
};
3. 享元工厂 (ShapeFactory)
  • 负责管理享元对象,保证相同的内部状态只创建一个对象:
class ShapeFactory {
private:
    std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象

public:
    std::shared_ptr<Shape> getCircle(int radius) {
        if (shapes.find(radius) == shapes.end()) {
            shapes[radius] = std::make_shared<Circle>(radius);
            std::cout << "Creating a circle with radius " << radius << std::endl;
        }
        return shapes[radius];
    }
};
4. 客户端
  • 客户端通过 ShapeFactory 获取共享对象,并将外部状态与内部状态结合:
auto circle1 = factory.getCircle(5); // 创建新对象
auto circle3 = factory.getCircle(5); // 复用已有对象
circle1->draw("red");   // 绘制红色圆形
circle3->draw("green"); // 绘制绿色圆形

优缺点

优点
  1. 减少内存使用
    • 通过共享对象,避免了重复创建相同对象,节省了内存。
  2. 提高系统性能
    • 减少了对象创建的时间和空间开销。
  3. 灵活性高
    • 外部状态与内部状态分离,可以独立管理。
缺点
  1. 复杂性增加
    • 系统需要额外的享元工厂来管理共享对象。
  2. 外部状态的管理困难
    • 客户端需要显式传递外部状态,增加了使用复杂性。

适用场景

  1. 系统有大量相似对象

    • 如文字处理系统中的字符对象,每个字符对象可以共享其字体、大小等内部状态。
  2. 内存消耗成为瓶颈

    • 系统中对象数量庞大,通过共享来减少内存占用。
  3. 对象的状态可以分为内部状态和外部状态

    • 内部状态可以共享,外部状态由客户端管理。

总结

享元模式通过共享相似对象来减少内存使用,是一种优化性能的重要模式。它适用于对象数量庞大且状态大部分可以共享的场景。


http://www.kler.cn/a/506342.html

相关文章:

  • 【Excel】【VBA】双列排序:坐标从Y从大到小排列之后相同Y坐标的行再对X从小到大排列
  • IvorySQL 4.0 之 Invisible Column 功能解析
  • docker安装mysql 5.7
  • Unity搭配VS Code使用
  • 神经网络常见操作(卷积)输入输出
  • 我这不需要保留本地修改, 只需要拉取远程更改
  • 电控管理平台
  • [Qt] QSS | Qt Designer | 选择器
  • Linux/MacOS中如何远程调试C/C++程序
  • 无公网IP 实现外网访问本地 Docker 部署 Navidrome
  • NanoKVM简单开箱测评和拆解,让普通电脑实现BMC/IPMI远程管理功能
  • Redis基础3-主从复制
  • 得物App利用技术赋能,打造潮流消费“新玩法”
  • 全面了解 Web 前端技术:从基础到实践
  • JavaScript中的`void 0`:一个古老而安全的`undefined`获取方式
  • mac m4 安装 node
  • ResNet (Residual Network) - 残差网络:深度卷积神经网络的突破
  • Three.js+Vue3+Vite物体位移、缩放与旋转(二)
  • 【MySQL】使用C语言链接
  • R语言基础| 方差分析
  • 浅谈云计算11 | 虚拟机的主要功能
  • (RAG系列)FastGPT批量添加索引
  • WXML模版语法-事件绑定
  • 前端常见的设计模式之【单例模式】
  • 【机器学习:二十三、迁移学习】
  • 冯·诺依曼体系结构:计算机科学的奠基石