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

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

  • 装饰模式:动态地给对象添加职责,而不改变对象的接口。它通过创建一系列装饰器类来实现这些职责的扩展,从而在运行时灵活地扩展对象的功能。
  • 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。它通过将抽象和实现放在不同的类层次结构中,并通过组合将它们连接起来,从而提高系统的灵活性和可扩展性。
相关推荐
幂简集成explinks1 天前
e签宝签署API更新实战:新增 signType 与 FDA 合规参数配置
后端·设计模式·开源
River4161 天前
Javer 学 c++(十三):引用篇
c++·后端
感哥1 天前
C++ std::set
c++
侃侃_天下1 天前
最终的信号类
开发语言·c++·算法
博笙困了1 天前
AcWing学习——差分
c++·算法
大飞pkz1 天前
【设计模式】C#反射实现抽象工厂模式
设计模式·c#·抽象工厂模式·c#反射·c#反射实现抽象工厂模式
努力也学不会java1 天前
【设计模式】抽象工厂模式
java·设计模式·oracle·抽象工厂模式
青草地溪水旁1 天前
设计模式(C++)详解—抽象工厂模式 (Abstract Factory)(2)
c++·设计模式·抽象工厂模式
青草地溪水旁1 天前
设计模式(C++)详解—抽象工厂模式 (Abstract Factory)(1)
c++·设计模式·抽象工厂模式
感哥1 天前
C++ std::vector
c++