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.总结

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

  • 装饰模式:动态地给对象添加职责,而不改变对象的接口。它通过创建一系列装饰器类来实现这些职责的扩展,从而在运行时灵活地扩展对象的功能。
  • 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。它通过将抽象和实现放在不同的类层次结构中,并通过组合将它们连接起来,从而提高系统的灵活性和可扩展性。
相关推荐
轻口味7 分钟前
【每日学点鸿蒙知识】Hap 安装失败、ArkTS 与C++ 数组转换、渐变遮罩效果等
c++·华为·harmonyos
YOULANSHENGMENG1 小时前
linux上使用cmake编译的方法
开发语言·c++
神仙别闹1 小时前
基于QT(C++)实现的坦克大战
数据库·c++·qt
float_六七1 小时前
头文件math/cmath
c++·算法·stl
小林熬夜学编程2 小时前
【Linux网络编程】第二十弹---熟练I/O多路转接:深入解析select机制与实战
linux·运维·服务器·c语言·开发语言·网络·c++
水宝的滚动歌词2 小时前
设计模式之适配器模式
设计模式·适配器模式
arong_xu4 小时前
C++23 格式化输出新特性详解: std::print 和 std::println
开发语言·c++·c++23
冷雨夜中漫步5 小时前
领域驱动设计(4)—绑定模型与实现
java·开发语言·笔记·后端·设计模式
JINGWHALE19 小时前
设计模式 结构型 外观模式(Facade Pattern)与 常见技术框架应用 解析
前端·人工智能·后端·设计模式·性能优化·系统架构·外观模式
玉带湖水位记录员9 小时前
外观模式——C++实现
c++·外观模式