设计模式每日硬核训练 Day 12:装饰器模式(Decorator Pattern)完整讲解与实战应用

🔄 回顾 Day 11:适配器模式小结

在 Day 11 中,我们学习了适配器模式(Adapter Pattern):

  • 用于将"不兼容"的接口适配为目标接口,解决新旧系统之间的桥接问题。
  • 强调"接口兼容、外部桥接",通常用于第三方组件、老旧库的接入。

而今天我们要讲解的装饰器模式,则是:

在不改变原始类结构的前提下,动态为对象添加功能,是继承的优雅替代。


一、装饰器模式的核心动机

✅ 什么是装饰器?

装饰器模式(Decorator Pattern)用于:

  • 将对象进行包装,在其行为之前/之后添加额外逻辑。
  • 避免子类膨胀(继承爆炸),提升灵活性与组合性。

🎯 场景动机:

  • IO 流中,数据流可多层压缩/加密/缓冲
  • GUI 元素,增加边框、滚动条、阴影等效果
  • 日志功能,输出前加时间戳、加颜色、记录文件

二、UML 结构图

复制代码
+----------------+
|   Component    |<------------------+
+----------------+                   |
| +operation()   |                   |
+----------------+                   |
        /\                            |
        ||                            |
+----------------+           +-----------------+
| ConcreteComponent |        |  Decorator      |
+----------------+           +-----------------+
                             | - component: Component* |
                             | +operation() override   |
                             +-----------------+
                                     /\
                                     ||
                        +---------------------------+
                        | ConcreteDecoratorA/B/...  |
                        +---------------------------+

三、角色解析

角色 职责说明
Component 抽象组件接口,定义操作行为
ConcreteComponent 实际的核心功能类
Decorator 抽象装饰器,持有组件引用,重写 operation
ConcreteDecorator 具体装饰功能的子类,添加增强行为

四、C++ 实现:消息输出增强系统

✅ Component 抽象接口

cpp 复制代码
class IMessage {
public:
    virtual void send(const std::string& content) = 0;
    virtual ~IMessage() = default;
};

✅ 具体实现类

cpp 复制代码
class SimpleMessage : public IMessage {
public:
    void send(const std::string& content) override {
        std::cout << content << std::endl;
    }
};

✅ 抽象装饰器

cpp 复制代码
class MessageDecorator : public IMessage {
protected:
    std::unique_ptr<IMessage> wrappee_;
public:
    MessageDecorator(std::unique_ptr<IMessage> wrappee)
        : wrappee_(std::move(wrappee)) {}
};

✅ 时间戳装饰器

cpp 复制代码
class TimestampDecorator : public MessageDecorator {
public:
    using MessageDecorator::MessageDecorator;

    void send(const std::string& content) override {
        std::cout << "[Time] 2025-04-12: ";
        wrappee_->send(content);
    }
};

✅ 加密装饰器(简单)

cpp 复制代码
class EncryptDecorator : public MessageDecorator {
public:
    using MessageDecorator::MessageDecorator;

    void send(const std::string& content) override {
        std::string encrypted = "<encrypted:" + content + ">";
        wrappee_->send(encrypted);
    }
};

✅ 使用示例

cpp 复制代码
int main() {
    std::unique_ptr<IMessage> message = std::make_unique<SimpleMessage>();

    message = std::make_unique<TimestampDecorator>(std::move(message));
    message = std::make_unique<EncryptDecorator>(std::move(message));

    message->send("Hello World!");
    return 0;
}

输出:

复制代码
[Time] 2025-04-12: <encrypted:Hello World!>

五、装饰器 vs 继承

比较项 装饰器 子类继承
可组合性 ✅ 支持任意层级嵌套 ❌ 单继承不支持组合
可扩展性 ✅ 添加装饰器即可 ❌ 添加功能需新建子类
运行时决定 ✅ 装饰器可动态组合 ❌ 继承结构在编译期固定

六、实战应用举例

场景 装饰器用途说明
C++ IO Stream std::istream → std::ifstream → std::istringstream
日志系统 添加标签、时间、线程 ID
游戏角色行为 攻击装饰:暴击 → 穿透 → 吸血
网络请求处理链 添加重试机制 → 添加限流 → 添加缓存
Web Filter 框架 Spring Filter Chain(Java 中广泛使用)

七、与其他结构型模式对比

模式 意图 是否更改原对象
Decorator 增强已有对象功能 ❌(包裹)
Proxy 控制访问、权限、懒加载 ❌(控制访问)
Adapter 接口转换,兼容老接口 ❌(桥接)
Bridge 接口与实现分离,双维度变化 ✅(实现层变化)

八、面试回答模板

"我们使用装饰器模式为日志系统添加了格式增强功能,比如加上时间戳、线程信息以及日志等级,而不需要改动原有的日志类。装饰器让我们可以灵活组合这些功能,并且在运行时动态配置,适合多种环境。"

✅ 建议强调运行时组合、非侵入式增强、支持多层扩展等特性。


九、记忆口诀

"增强不改类,功能可叠加;运行时组合,结构更优雅。"


十、明日预告:Day 13

桥接模式(Bridge Pattern):将接口与实现解耦,适用于双维度扩展场景。

相关推荐
找不到、了6 小时前
Java设计模式之<建造者模式>
java·设计模式·建造者模式
LoveC52111 小时前
设计模式之适配器模式
设计模式·适配器模式
永卿00112 小时前
设计模式-责任链模式
java·设计模式·责任链模式
Codebee17 小时前
OneCode 3.0 智能数据处理:快速视图中的智能分页与 @PageBar 注解详解
后端·设计模式
Codebee17 小时前
OneCode 3.0智能分页拦截器深度解析:从拦截机制到性能优化
后端·设计模式
是2的10次方啊17 小时前
🎭 Java设计模式详解:让代码优雅如诗的秘密武器
设计模式
python_13618 小时前
python设计模式-工厂模式
开发语言·python·设计模式
k *18 小时前
c++:设计模式训练
设计模式
牛奶咖啡1321 小时前
学习设计模式《二十》——解释器模式
学习·设计模式·解释器模式·认识解释器模式·解释器模式的优缺点·何时使用解释器模式·解释器模式的示例
北_鱼1 天前
设计模式1:创建型模式
java·设计模式·软件工程·代码规范·设计规范