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

铁佛  金牌会员 | 2025-1-21 23:16:30 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 877|帖子 877|积分 2631

享元模式 (Flyweight)

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

意图



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

利用场景


  • 大量相似对象

    • 系统中存在许多共享的对象,这些对象的状态大部门是相同的。

  • 状态可以分为内部状态和外部状态

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

  • 节流内存

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


参与者角色


  • 享元接口 (Flyweight)

    • 定义共享对象的公共接口。

  • 具体享元 (ConcreteFlyweight)

    • 实现享元接口,存储可以共享的内部状态。

  • 非共享享元 (UnsharedFlyweight)

    • 不可以共享的子类,通常会组合共享的享元对象。

  • 享元工厂 (FlyweightFactory)

    • 创建并管理享元对象,确保共享对象的唯一性。

  • 客户端 (Client)

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


示例代码

以下代码展示了怎样利用享元模式来共享图形对象,例如圆形。
  1. #include <iostream>
  2. #include <string>
  3. #include <unordered_map>
  4. #include <memory>
  5. // 享元接口:图形
  6. class Shape {
  7. public:
  8.     virtual ~Shape() = default;
  9.     virtual void draw(const std::string& color) const = 0; // 外部状态为颜色
  10. };
  11. // 具体享元类:圆形
  12. class Circle : public Shape {
  13. private:
  14.     int radius; // 内部状态:半径
  15. public:
  16.     Circle(int r) : radius(r) {}
  17.     void draw(const std::string& color) const override {
  18.         std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;
  19.     }
  20. };
  21. // 享元工厂:管理享元对象
  22. class ShapeFactory {
  23. private:
  24.     std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象
  25. public:
  26.     std::shared_ptr<Shape> getCircle(int radius) {
  27.         if (shapes.find(radius) == shapes.end()) {
  28.             shapes[radius] = std::make_shared<Circle>(radius);
  29.             std::cout << "Creating a circle with radius " << radius << std::endl;
  30.         }
  31.         return shapes[radius];
  32.     }
  33. };
  34. // 客户端代码
  35. int main() {
  36.     ShapeFactory factory;
  37.     // 获取共享的圆形对象
  38.     auto circle1 = factory.getCircle(5);
  39.     auto circle2 = factory.getCircle(10);
  40.     auto circle3 = factory.getCircle(5); // 共享对象
  41.     // 使用享元对象绘制
  42.     circle1->draw("red");   // 外部状态:红色
  43.     circle2->draw("blue");  // 外部状态:蓝色
  44.     circle3->draw("green"); // 外部状态:绿色
  45.     return 0;
  46. }
复制代码

代码解析

1. 享元接口 (Shape)



  • 定义了 draw 方法,用于绘制图形,并吸取外部状态作为参数:
  1. class Shape {
  2. public:
  3.     virtual ~Shape() = default;
  4.     virtual void draw(const std::string& color) const = 0;
  5. };
复制代码
2. 具体享元类 (Circle)



  • 实现了 Shape 接口,存储可以共享的内部状态(如半径):
  1. class Circle : public Shape {
  2. private:
  3.     int radius; // 内部状态
  4. public:
  5.     Circle(int r) : radius(r) {}
  6.     void draw(const std::string& color) const override {
  7.         std::cout << "Drawing a circle with radius " << radius << " and color " << color << std::endl;
  8.     }
  9. };
复制代码
3. 享元工厂 (ShapeFactory)



  • 负责管理享元对象,包管相同的内部状态只创建一个对象:
  1. class ShapeFactory {
  2. private:
  3.     std::unordered_map<int, std::shared_ptr<Shape>> shapes; // 缓存共享对象
  4. public:
  5.     std::shared_ptr<Shape> getCircle(int radius) {
  6.         if (shapes.find(radius) == shapes.end()) {
  7.             shapes[radius] = std::make_shared<Circle>(radius);
  8.             std::cout << "Creating a circle with radius " << radius << std::endl;
  9.         }
  10.         return shapes[radius];
  11.     }
  12. };
复制代码
4. 客户端



  • 客户端通过 ShapeFactory 获取共享对象,并将外部状态与内部状态结合:
  1. auto circle1 = factory.getCircle(5); // 创建新对象
  2. auto circle3 = factory.getCircle(5); // 复用已有对象
  3. circle1->draw("red");   // 绘制红色圆形
  4. circle3->draw("green"); // 绘制绿色圆形
复制代码

优缺点

优点


  • 减少内存利用

    • 通过共享对象,制止了重复创建相同对象,节流了内存。

  • 提高系统性能

    • 减少了对象创建的时间和空间开销。

  • 灵活性高

    • 外部状态与内部状态分离,可以独立管理。

缺点


  • 复杂性增加

    • 系统需要额外的享元工厂来管理共享对象。

  • 外部状态的管理困难

    • 客户端需要显式通报外部状态,增加了利用复杂性。


实用场景


  • 系统有大量相似对象

    • 如笔墨处理系统中的字符对象,每个字符对象可以共享其字体、巨细等内部状态。

  • 内存消耗成为瓶颈

    • 系统中对象数量巨大,通过共享来减少内存占用。

  • 对象的状态可以分为内部状态和外部状态

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


总结

享元模式通过共享相似对象来减少内存利用,是一种优化性能的告急模式。它实用于对象数量巨大且状态大部门可以共享的场景。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

铁佛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表