C++实现设计模式---装饰器模式 (Decorator)

embedded/2025/1/19 13:54:52/

装饰器模式 (Decorator)

装饰器模式 是一种结构型设计模式,它允许动态地将责任附加到对象上,既可以在运行时给一个对象添加功能,又不会影响其他对象的功能。


意图

  • 动态地扩展对象的功能。
  • 避免创建过多的子类,通过装饰器来“包装”对象,添加新功能。
  • 保持类的单一职责和开放封闭原则。

使用场景

  1. 系统需要动态地添加功能给对象
    • 如UI框架中的组件装饰,能动态增加功能(如窗口的滚动条、边框等)。
  2. 不希望通过继承来扩展对象功能
    • 继承可能会导致类的数量激增,装饰器模式能够解决这个问题。
  3. 功能扩展需要灵活控制
    • 可以在不同的对象上应用不同的装饰,不会互相影响。

参与者角色

  1. 组件接口 (Component)
    • 定义基本对象行为的接口,所有的装饰器和具体对象都需要实现此接口。
  2. 具体组件 (ConcreteComponent)
    • 具体实现基本行为的对象。
  3. 装饰器 (Decorator)
    • 持有组件的引用,并实现组件接口,增强功能。
  4. 具体装饰器 (ConcreteDecorator)
    • 通过调用被装饰对象的方法来添加额外功能。

示例代码

以下代码展示了如何使用装饰器模式扩展一个简单的咖啡类。

#include <iostream>
#include <string>// 组件接口
class Beverage {
public:virtual ~Beverage() = default;virtual std::string getDescription() const = 0;virtual double cost() const = 0;
};// 具体组件:咖啡
class Coffee : public Beverage {
public:std::string getDescription() const override {return "Coffee";}double cost() const override {return 5.0;}
};// 装饰器基类
class BeverageDecorator : public Beverage {
protected:Beverage* beverage;public:BeverageDecorator(Beverage* b) : beverage(b) {}virtual ~BeverageDecorator() = default;
};// 具体装饰器:加入牛奶
class MilkDecorator : public BeverageDecorator {
public:MilkDecorator(Beverage* b) : BeverageDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Milk";}double cost() const override {return beverage->cost() + 1.0;}
};// 具体装饰器:加入糖
class SugarDecorator : public BeverageDecorator {
public:SugarDecorator(Beverage* b) : BeverageDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Sugar";}double cost() const override {return beverage->cost() + 0.5;}
};// 客户端代码
int main() {Beverage* coffee = new Coffee();  // 创建基本的咖啡std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;// 加入牛奶的装饰coffee = new MilkDecorator(coffee);std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;// 再加入糖的装饰coffee = new SugarDecorator(coffee);std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;// 清理内存delete coffee;return 0;
}

代码解析

1. 组件接口

  • Beverage 类是所有具体组件和装饰器的公共接口,定义了所有具体对象的行为:
class Beverage {
public:virtual ~Beverage() = default;virtual std::string getDescription() const = 0;virtual double cost() const = 0;
};

2. 具体组件

  • Coffee 是具体的组件,提供了描述和计算费用的功能:
class Coffee : public Beverage {
public:std::string getDescription() const override {return "Coffee";}double cost() const override {return 5.0;}
};

3. 装饰器基类

  • BeverageDecorator 继承了 Beverage,并持有一个 Beverage 对象,能够动态地扩展其功能:
class BeverageDecorator : public Beverage {
protected:Beverage* beverage;public:BeverageDecorator(Beverage* b) : beverage(b) {}virtual ~BeverageDecorator() = default;
};

4. 具体装饰器

  • MilkDecoratorSugarDecorator 是具体的装饰器类,分别增加了 MilkSugar 的功能:
class MilkDecorator : public BeverageDecorator {
public:MilkDecorator(Beverage* b) : BeverageDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Milk";}double cost() const override {return beverage->cost() + 1.0;}
};
class SugarDecorator : public BeverageDecorator {
public:SugarDecorator(Beverage* b) : BeverageDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Sugar";}double cost() const override {return beverage->cost() + 0.5;}
};

5. 客户端

  • 客户端可以按需为原始对象添加装饰,每次调用 getDescriptioncost 时,都能看到新添加的功能:
int main() {Beverage* coffee = new Coffee();  std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;coffee = new MilkDecorator(coffee);std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;coffee = new SugarDecorator(coffee);std::cout << coffee->getDescription() << " Cost: $" << coffee->cost() << std::endl;delete coffee;return 0;
}

优缺点

优点

  1. 动态扩展功能
    • 可以在运行时为对象添加新功能。
  2. 避免子类数量暴增
    • 通过装饰器而不是继承来扩展功能,避免了类的膨胀。
  3. 高灵活性
    • 可以灵活地为不同的对象选择不同的装饰器进行组合。

缺点

  1. 增加系统复杂性
    • 过多的装饰器可能使系统变得复杂,难以理解。
  2. 装饰器的顺序问题
    • 装饰器的顺序会影响最终对象的行为。

适用场景

  • 动态地给一个对象添加功能,例如为一个对象添加不同的用户界面样式、不同的服务功能。
  • 避免使用继承,需要在运行时动态地扩展功能。

总结

装饰器模式是一种非常灵活的模式,能够动态地给对象添加新功能,避免了继承带来的问题。通过组合装饰器类,能够灵活地为对象组合不同的功能,在很多场景中非常有用。



http://www.ppmy.cn/embedded/155235.html

相关文章

unity——Prejct3——背景音乐

1.音乐数据结构类 using System.Collections; using System.Collections.Generic; using UnityEngine;//音乐数据结构类 public class MusicData {//背景音乐 音效 开关public bool musicOpen true;public bool soundOpen true;//背景音乐 音效 大小public float musicValu…

LabVIEW与WPS文件格式的兼容性

LabVIEW 本身并不原生支持将文件直接保存为 WPS 格式&#xff08;如 WPS 文档或表格&#xff09;。然而&#xff0c;可以通过几种间接的方式实现这一目标&#xff0c;确保您能将 LabVIEW 中的数据或报告转换为 WPS 可兼容的格式。以下是几种常见的解决方案&#xff1a; ​ 导出…

解决Element Plus el-date-picker组件清空时,触发两次change的问题

问题 el-date-picker 组件在选择日期范围时会触发两次 change 事件。当用户选择了范围的开始时&#xff0c;会立即触发一次 change 事件。而当用户选择了范围的结束时&#xff0c;又会触发一次 change 事件。 解决方法 1. 延迟更新 <template><div>选择日期--{…

LeetCode 热题 100 | 矩阵

矩阵基础 使用哈希数组来标记当前行或者列是否出现0按层模拟旋转90度可以先水平翻&#xff0c;然后再对角线翻 73. 矩阵置零 题目讲解&#xff1a;LeetCode 重点&#xff1a; 使用标记数组&#xff1a;用两个标记数组分别记录每一行和每一列是否有零出现。使用两个标记变量&…

Kaggle欺诈检测:使用生成对抗网络(GAN)解决正负样本极度不平衡问题

### Kaggle欺诈检测&#xff1a;使用生成对抗网络&#xff08;GAN&#xff09;解决正负样本极度不平衡问题 #### 引言 在金融领域中&#xff0c;欺诈检测是一项至关重要的任务。然而&#xff0c;欺诈交易数据往往呈现出正负样本极度不平衡的特点&#xff0c;这给机器学习模型…

leetcode 407. 接雨水 II

题目&#xff1a;407. 接雨水 II - 力扣&#xff08;LeetCode&#xff09; 堆bfs。 模拟水流出去的过程。先把边缘的单元都加到堆里&#xff0c;从堆顶最小的单元开始bfs&#xff0c;遍历到的单元的四周&#xff0c;都会从该单元流出去&#xff0c;四周的单元的剩余水量高度m…

【RK3588嵌入式图形编程】-SDL2-创建应用窗口

创建应用窗口 文章目录 创建应用窗口1、认识SDL及安装1.1 什么是SDL1.2 SDL安装2、应用程序准备3、应用程序实现3.1 创建窗口3.2 Window类3.3 Surface3.4 SDL_FillRect3.5 颜色和SDL_MapRGB()3.6 SDL_UpdateWindowSurface3.7 SDL_DestroyWindow()3.8 main函数4、总结SDL2是一个…

业务架构、数据架构、应用架构和技术架构

TOGAF(The Open Group Architecture Framework)是一个广泛应用的企业架构框架&#xff0c;旨在帮助组织高效地进行架构设计和管理。 TOGAF 的核心就是由我们熟知的四大架构领域组成:业务架构、数据架构、应用架构和技术架构。 企业数字化架构设计中的最常见要素是4A 架构。 4…