← 返回题目列表

装饰器模式在业务系统中有哪些应用场景?

高频 中等 第 10 / 25 题 更新于 2026/07/28
装饰器模式业务场景运行时组合工程实践

简化版

装饰器模式适合业务中“基础能力稳定、附加能力可选组合”的场景,例如 HTTP 客户端叠加日志、重试、签名,文件处理叠加压缩、加密,文本处理叠加过滤、脱敏、格式化。它能让每个增强独立维护,并按需组合。

详细版

业务系统中常见装饰器场景包括:

  • HTTP 客户端:日志、重试、限流、签名、监控;
  • 文件处理:压缩、加密、校验、上传;
  • 文本处理:敏感词过滤、脱敏、格式化、统计;
  • 消息发送:模板渲染、签名、压缩、埋点;
  • 数据源访问:缓存、日志、权限、指标采集;
  • UI 组件:边框、阴影、滚动条、拖拽能力。

例如 HTTP 客户端:

HttpClient client = new MetricsHttpClient(
        new RetryHttpClient(
                new SignHttpClient(
                        new DefaultHttpClient()
                )
        )
);

每一层只做一件事:

  • DefaultHttpClient 负责真正发送请求;
  • SignHttpClient 负责签名;
  • RetryHttpClient 负责失败重试;
  • MetricsHttpClient 负责统计耗时和结果。

这样新增一个限流能力,只需要新增 RateLimitHttpClient,不用修改原来的客户端实现。

装饰器尤其适合做 SDK、基础设施组件和可插拔增强链。

完整版教学

一、HTTP 客户端增强链

很多项目都会封装 HTTP 客户端。基础客户端只负责发送请求:

interface HttpClient {
    Response execute(Request request);
}

但真实系统里,发送请求前后可能有很多通用逻辑:

  • 打日志;
  • 添加签名;
  • 压缩请求体;
  • 失败重试;
  • 统计耗时;
  • 限流;
  • 熔断。

如果全部写进 DefaultHttpClient,这个类会变得很重。

使用装饰器后:

HttpClient client = new LoggingClient(
        new RetryClient(
                new SigningClient(
                        new DefaultHttpClient()
                )
        )
);

每个增强独立,组合顺序也可以集中管理。

二、文件处理链

文件处理也很适合装饰器。

基础能力是读写文件:

interface FileProcessor {
    byte[] read();
    void write(byte[] data);
}

附加能力可以包括:

  • 压缩;
  • 加密;
  • 校验摘要;
  • 记录审计日志;
  • 上传到远程存储。

例如写入顺序:

原始数据 -> 压缩 -> 加密 -> 写入

读取顺序:

读取 -> 解密 -> 解压 -> 原始数据

这种前后对称的处理链,很适合用装饰器表达。

三、文本处理和内容安全

文本处理系统经常需要多个可组合步骤:

  • 去 HTML;
  • 敏感词过滤;
  • 手机号脱敏;
  • 关键词高亮;
  • 统计字数;
  • 格式化输出。

可以定义:

interface TextProcessor {
    String process(String text);
}

然后组合:

TextProcessor processor = new MaskPhoneDecorator(
        new SensitiveWordDecorator(
                new PlainTextProcessor()
        )
);

如果某个业务只需要脱敏,不需要敏感词过滤,就换一个组合即可。

四、消息发送增强

消息发送也有装饰器空间:

MessageSender sender = new TraceMessageSender(
        new TemplateMessageSender(
                new DefaultMessageSender()
        )
);

每层职责:

  • 模板装饰器负责渲染模板;
  • Trace 装饰器负责埋点;
  • 签名装饰器负责安全校验;
  • 默认发送器负责真正发送。

如果不同渠道需要不同增强链,可以用工厂按渠道装配装饰器。

五、什么时候业务里不适合装饰器

如果业务流程本身有强分支、强状态流转,装饰器不一定合适。

例如订单状态从待支付到已支付、已取消、已退款,这种状态流转更适合状态模式、策略模式或领域服务,不适合用装饰器一层层包。

装饰器适合附加能力组合,不适合表达复杂业务主流程。

判断标准是:增强是否可以独立存在、是否围绕同一接口、是否能自由组合。如果答案是肯定,装饰器就比较合适。

六、业务增强是否正交可组合

HTTP 请求依次经过鉴权 2 ms、重试判断 1 ms、日志 1 ms;若首次远程调用 30 ms 成功,总耗时约 34 ms,重试装饰器只在失败时增加后续调用。

base client <- timeout <- retry <- auth <- metrics

这个推演把模式带来的收益和成本放在同一条调用链上。设计评审时既要确认结果正确,也要确认额外层次没有改变原有契约。

七、边界、代价与验证

检查维度应确认的内容
正确性业务装饰器应一次只增加一种可独立测试的能力,否则很快退化成隐藏的上帝对象。
适用边界事务主流程、复杂审批和跨步骤补偿通常不是装饰器职责;这些场景需要显式流程和状态。
测试证据覆盖正常路径、异常路径、空值或未知类型,并断言调用次数与顺序
运行成本记录额外对象、调用层数、延迟、线程或内存开销,不用模式名称代替测量

模式落地后要用单元测试验证独立职责,用集成测试验证对象装配和真实调用入口。涉及并发、远程或异步时,还要补充竞态、超时、重复执行与资源释放测试。

易错点:业务装饰器应一次只增加一种可独立测试的能力,否则很快退化成隐藏的上帝对象。

八、常见误区与追问

  • 误区:任何横切逻辑都适合做装饰器。 只有能围绕同一组件契约独立叠加的职责才合适,强流程依赖不适合。
  • 误区:装饰器可以任意改变组件接口。 透明装饰依赖共同的 Component 契约;随意增加只能向下转型调用的方法,会破坏可替换性和继续组合的能力。
  • 误区:示例代码能运行,就代表模式边界设计正确。 能运行只证明一条路径,仍要检查异常、并发、顺序、生命周期以及新增实现时是否修改稳定代码。
  • 追问:业务装饰链由谁装配更稳妥? 由工厂、依赖注入配置或专门组装器集中决定,避免各调用点产生不同顺序。
  • 追问:装饰器链越长,扩展性就一定越好吗? 不一定;链越长,顺序、异常传播和排障成本越高,应由装配层集中管理并限制职责粒度。
  • 追问:怎样验证这套设计没有改变原有语义? 先做基线行为测试,再对新增层验证返回值、异常类型、调用次数和顺序;性能敏感处还要比较改造前后的量化指标。

九、加强记忆

业务系统里的装饰器常出现在 HTTP 客户端、文件处理、文本处理、消息发送这些“基础能力 + 多个可选增强”的地方。主流程别装饰,附加能力才装饰。