C++ 设计模式:享元模式(Flyweight Pattern)

链接:C++ 设计模式
链接:C++ 设计模式 - 单例模式

享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享尽可能多的相同对象来减少内存使用和提高性能。享元模式适用于大量细粒度对象的场景,这些对象之间有很多相同的部分,可以通过共享来减少内存消耗。

1.问题分析

在开发中,尤其是在需要大量细粒度对象的场景中,内存使用和性能优化是两个重要的考虑因素。例如,在图形界面、文本编辑器、游戏开发等领域,可能会有大量相似或相同的对象需要频繁创建和使用。如果每次都创建新的对象,不仅会占用大量内存,还会导致性能下降。

为了解决这些问题,我们可以结合工厂方法模式和延迟初始化来实现享元模式。具体来说,我们可以定义一个工厂类,通过延迟初始化和独立工厂函数来动态创建和缓存具体的对象。

2.实现步骤:

  1. 定义享元接口:定义一个抽象的接口,包含一个执行方法。
  2. 实现具体享元类:实现享元接口,定义具体的类。
  3. 定义独立工厂函数:定义一个独立的工厂函数,用于根据类型动态创建具体的对象。
  4. 实现享元工厂:实现一个工厂类,通过延迟初始化和独立工厂函数来动态创建和缓存具体的对象。
  5. 客户端代码:使用享元工厂获取具体对象,并执行。

3.代码示例

以机器人舞蹈动作作为示例。

3.1.定义享元接口

cpp 复制代码
// 享元接口
class DanceMove {
 public:
  virtual ~DanceMove() = default;
  virtual void execute() = 0;
};

3.2.实现具体享元类

cpp 复制代码
// 具体享元类1,抬手动作
class RaiseHand : public DanceMove {
 public:
  void execute() override { std::cout << "Executing Raise Hand Move" << std::endl; }
};
cpp 复制代码
// 具体享元类2,转身动作
class TurnAround : public DanceMove {
 public:
  void execute() override { std::cout << "Executing Turn Around Move" << std::endl; }
};
cpp 复制代码
// 具体享元类3,踢腿动作
class KickLeg : public DanceMove {
 public:
  void execute() override { std::cout << "Executing Kick Leg Move" << std::endl; }
};

3.3.定义独立工厂函数

cpp 复制代码
// 独立工厂函数
std::shared_ptr<DanceMove> createDanceMove(const std::string& type) {
  if (type == "RaiseHand") {
    return std::make_shared<RaiseHand>();
  } else if (type == "TurnAround") {
    return std::make_shared<TurnAround>();
  } else if (type == "KickLeg") {
    return std::make_shared<KickLeg>();
  } else {
    return nullptr;
  }
}

3.4.实现享元工厂类

cpp 复制代码
// 享元工厂
class DanceMoveFactory {
 public:
  // 获取舞蹈动作
  std::shared_ptr<DanceMove> getDanceMove(const std::string& type) {
    auto it = danceMoveMap_.find(type);
    if (it != danceMoveMap_.end()) {
      return it->second;
    } else {
      // 创建动作
      std::shared_ptr<DanceMove> danceMove = createDanceMove(type);
      if (danceMove) {
        danceMoveMap_[type] = danceMove;
        return danceMove;
      } else {
        throw std::runtime_error("Dance move type not recognized: " + type);
      }
    }
  }

 private:
  std::unordered_map<std::string, std::shared_ptr<DanceMove>> danceMoveMap_;
};

3.5.客户端代码

cpp 复制代码
// 客户端代码
int main() {
  DanceMoveFactory factory;

  try {
    // 获取并执行舞蹈动作
    auto raiseHand = factory.getDanceMove("RaiseHand");
    raiseHand->execute();

    auto turnAround = factory.getDanceMove("TurnAround");
    turnAround->execute();

    auto kickLeg = factory.getDanceMove("KickLeg");
    kickLeg->execute();

    // 再次获取舞蹈动作,验证是否共享了相同类型的动作对象
    auto raiseHand2 = factory.getDanceMove("RaiseHand");
    raiseHand2->execute();

    std::cout << "raiseHand address: " << raiseHand.get() << std::endl;
    std::cout << "raiseHand2 address: " << raiseHand2.get() << std::endl;

    // 尝试获取未注册的舞蹈动作
    auto unknownMove = factory.getDanceMove("UnknownMove");
    unknownMove->execute();
  } catch (const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }

  return 0;
}
相关推荐
3壹2 分钟前
数据结构精讲:栈与队列实战指南
c语言·开发语言·数据结构·c++·算法
aaaweiaaaaaa29 分钟前
c++基础学习(学习蓝桥杯 ros2有C基础可看)
c++·学习·蓝桥杯·lambda·ros2·智能指针·c++类
一拳一个呆瓜1 小时前
【MFC】对话框属性:字体 (Font Name) 和 大小 (Font Size)
c++·mfc
郝学胜-神的一滴1 小时前
基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
c++·qt·线性代数·矩阵·游戏引擎·图形渲染
啊?啊?1 小时前
14 C++ STL 容器实战:stack/list 模拟实现指南 + priority_queue 用法及避坑技巧
c++·
汉克老师2 小时前
第十四届蓝桥杯青少组C++选拔赛[2023.2.12]第二部分编程题(4、最大空白区)
c++·算法·蓝桥杯·蓝桥杯c++·c++蓝桥杯
羚羊角uou2 小时前
【Linux】匿名管道和进程池
linux·c++·算法
曙曙学编程3 小时前
stm32——独立看门狗,RTC
c语言·c++·stm32·单片机·嵌入式硬件
励志不掉头发的内向程序员3 小时前
C++进阶——多态
开发语言·c++·学习
楼田莉子4 小时前
C++算法专题学习:栈相关的算法
开发语言·c++·算法·leetcode