C++ 设计模式:装饰模式(Decorator Pattern)

链接:C++ 设计模式
链接:C++ 设计模式 - 桥接模式

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰模式通过创建一个装饰类来包装原始类,从而在保持类接口不变的情况下,动态地扩展对象的功能。

1.适用场景

  1. 需要动态扩展对象的功能:当需要在运行时动态地为对象添加功能,而不是在编译时确定这些功能时。
  2. 功能可以按需组合:当对象的功能可以通过多种方式组合,并且这些组合是动态变化的。
  3. 避免类爆炸:如果使用继承来扩展功能,会导致类的数量急剧增加,因为每种功能组合都需要一个新的子类。装饰模式通过组合装饰器来避免这个问题。

2.实现步骤

  1. 定义组件接口:定义一个接口,描述基本组件的行为。
  2. 实现具体组件:实现基本组件类,提供组件的基本功能。
  3. 定义装饰器基类:创建一个装饰器基类,继承自组件接口,并持有一个组件对象的引用。
  4. 实现具体装饰器:实现具体装饰器类,继承自装饰器基类,并在扩展功能的方法中调用被装饰的组件对象的方法。
  5. 动态组合装饰器:在客户端代码中,动态地将装饰器组合在一起,扩展组件的功能。

3.代码示例

以机器人的任务扩展作为示例。

3.1.组件接口

cpp 复制代码
class Robot {
 public:
  virtual ~Robot() = default;
  virtual void performTask() = 0;
};

3.2.基本组件

cpp 复制代码
// 具备基本功能
class BasicRobot : public Robot {
 public:
  void performTask() override { std::cout << "Performing basic tasks." << std::endl; }
};

3.3.装饰器基类

cpp 复制代码
// 继承自组件接口
class RobotDecorator : public Robot {
 public:
  RobotDecorator(std::shared_ptr<Robot> robot) : decoratedRobot(robot) {}

  void performTask() override { decoratedRobot->performTask(); }

 protected:
  std::shared_ptr<Robot> decoratedRobot;
};

3.4.具体装饰器

cpp 复制代码
// 具体装饰器1:添加播放音乐功能
class MusicPlayerDecorator : public RobotDecorator {
 public:
  MusicPlayerDecorator(std::shared_ptr<Robot> robot) : RobotDecorator(robot) {}

  void performTask() override {
    RobotDecorator::performTask();
    playMusic();
  }

 private:
  void playMusic() { std::cout << "Playing music." << std::endl; }
};
cpp 复制代码
// 具体装饰器2:添加拍照功能
class CameraDecorator : public RobotDecorator {
 public:
  CameraDecorator(std::shared_ptr<Robot> robot) : RobotDecorator(robot) {}

  void performTask() override {
    RobotDecorator::performTask();
    takePhoto();
  }

 private:
  void takePhoto() { std::cout << "Taking a photo." << std::endl; }
};
cpp 复制代码
// 具体装饰器3:添加导航功能
class NavigationDecorator : public RobotDecorator {
 public:
  NavigationDecorator(std::shared_ptr<Robot> robot) : RobotDecorator(robot) {}

  void performTask() override {
    RobotDecorator::performTask();
    navigate();
  }

 private:
  void navigate() { std::cout << "Navigating to the destination." << std::endl; }
};

3.5.动态组合

cpp 复制代码
int main() {
    // 创建一个基本机器人
    std::shared_ptr<Robot> basicRobot = std::make_shared<BasicRobot>();

    // 添加播放音乐功能
    std::shared_ptr<Robot> musicPlayerRobot = std::make_shared<MusicPlayerDecorator>(basicRobot);

    // 添加播放音乐和拍照功能
    std::shared_ptr<Robot> cameraRobot = std::make_shared<CameraDecorator>(musicPlayerRobot);

    // 添加播放音乐和导航功能
    std::shared_ptr<Robot> fullFeaturedRobot = std::make_shared<NavigationDecorator>(musicPlayerRobot );

    // 执行任务
    std::cout << "Basic Robot:" << std::endl;
    basicRobot->performTask();

    std::cout << "\nMusic Player Robot:" << std::endl;
    musicPlayerRobot->performTask();

    std::cout << "\nCamera Robot:" << std::endl;
    cameraRobot->performTask();

    std::cout << "\nFull Featured Robot:" << std::endl;
    fullFeaturedRobot->performTask();

    return 0;
}

4.总结

装饰模式和桥接模式的区别:

  • 装饰模式:动态地给对象添加职责,而不改变对象的接口。它通过创建一系列装饰器类来实现这些职责的扩展,从而在运行时灵活地扩展对象的功能。
  • 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。它通过将抽象和实现放在不同的类层次结构中,并通过组合将它们连接起来,从而提高系统的灵活性和可扩展性。
相关推荐
JANGHIGH11 分钟前
c++ std::list使用笔记
c++·笔记·list
画个逗号给明天"18 分钟前
C++STL容器之list
开发语言·c++
Lqingyyyy2 小时前
P2865 [USACO06NOV] Roadblocks G 与最短路的路径可重复的严格次短路
开发语言·c++·算法
C语言小火车2 小时前
深入解析C++26 Execution Domain:设计原理与实战应用
java·开发语言·c++·异构计算调度·c++26执行模型·domain定制
ox00803 小时前
C++ 设计模式-中介者模式
c++·设计模式·中介者模式
黄铎彦3 小时前
使用GDI+、文件和目录和打印API,批量将图片按文件名分组打包成PDF
c++·windows·pdf
Ciderw4 小时前
LLVM编译器简介
c++·golang·编译·编译器·gcc·llvm·基础设施
扣丁梦想家4 小时前
设计模式教程:中介者模式(Mediator Pattern)
设计模式·中介者模式
花王江不语4 小时前
设计模式学习笔记
笔记·学习·设计模式
和光同尘@4 小时前
74. 搜索二维矩阵(LeetCode 热题 100)
数据结构·c++·线性代数·算法·leetcode·职场和发展·矩阵