Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

装饰器模式

装饰器模式用于在不修改原对象代码的情况下,动态给对象增加功能。

一句话理解:接口不变,外面包一层,能力增强。

解决什么问题

如果要给一个对象不断增加功能,直接继承会导致类爆炸。

例如输入流可能需要:

  • 缓冲能力。
  • 解压能力。
  • 解密能力。
  • 统计读取字节数。

这些能力可以任意组合,如果都用继承,会产生大量组合类。装饰器模式通过“包装对象”解决这个问题。

基本结构

text
Component
  ^ 
  |
ConcreteComponent
  ^
  |
Decorator -> Component
  ^
  |
ConcreteDecorator

角色:

  • Component:统一接口。
  • ConcreteComponent:原始对象。
  • Decorator:装饰器基类,持有一个 Component
  • ConcreteDecorator:具体增强逻辑。

Java 示例

基础接口:

java
interface Notifier {
    void send(String message);
}

原始对象:

java
class EmailNotifier implements Notifier {
    public void send(String message) {
        System.out.println("email: " + message);
    }
}

装饰器基类:

java
abstract class NotifierDecorator implements Notifier {
    protected final Notifier target;

    protected NotifierDecorator(Notifier target) {
        this.target = target;
    }
}

短信增强:

java
class SmsNotifierDecorator extends NotifierDecorator {
    SmsNotifierDecorator(Notifier target) {
        super(target);
    }

    public void send(String message) {
        target.send(message);
        System.out.println("sms: " + message);
    }
}

日志增强:

java
class LogNotifierDecorator extends NotifierDecorator {
    LogNotifierDecorator(Notifier target) {
        super(target);
    }

    public void send(String message) {
        System.out.println("before send log");
        target.send(message);
        System.out.println("after send log");
    }
}

使用:

java
Notifier notifier = new LogNotifierDecorator(
        new SmsNotifierDecorator(
                new EmailNotifier()
        )
);

notifier.send("server is down");

JDK 中的例子

Java IO 是典型装饰器:

java
InputStream inputStream = new BufferedInputStream(
        new FileInputStream("app.log")
);

FileInputStream 负责读取文件,BufferedInputStream 增加缓冲能力,它们都实现 InputStream

使用场景

  • 给对象动态增加功能。
  • 功能可以叠加组合。
  • 不想修改原类。
  • 继承会导致组合类太多。
  • 输入输出流、过滤器、请求包装等场景。

优点

  • 比继承更灵活。
  • 可以运行时组合多个增强。
  • 符合开闭原则。
  • 原对象和增强逻辑分离。

缺点

  • 包装层太多时调试不直观。
  • 对象链过长会增加理解成本。
  • 多个装饰器顺序不同,结果可能不同。

和代理模式的区别

模式重点
装饰器增强对象能力,多个增强可叠加
代理控制对象访问,常用于权限、懒加载、远程调用

两者结构很像,但设计意图不同。

实战注意

装饰器最好保持和原对象相同的接口。调用方应该不知道自己拿到的是原对象还是装饰后的对象。

以工程实践沉淀知识,以文档复盘成长。