接口是装饰器模式的基石,它通过统一契约、组合复用和限制职责扩展范围,实现清晰、安全、可组合的动态功能增强。

Java 中接口是装饰器模式的基石,它让动态扩展职责变得清晰、安全且可组合。关键不在于“加语法糖”,而在于用接口统一契约,靠组合实现叠加。
接口定义统一行为契约
所有参与者——原始功能类、抽象装饰器、具体装饰器——都必须实现同一个接口。这个接口就是职责扩展的“协议”。比如:
-
PaymentService 接口声明
void pay(double amount),它不关心谁实现,只保证调用方能安心调用 - AlipayService 实现它,专注支付逻辑
- LoggingPaymentDecorator 和 AuthPaymentDecorator 也都实现它,意味着它们“看起来”和 AlipayService 完全一样
客户端代码只依赖接口,完全不知道背后是纯实现、一层日志,还是三层嵌套(鉴权+缓存+日志)。这就是透明性与替换性的来源。
装饰器通过组合复用接口能力
每个具体装饰器内部持有一个接口类型的引用(如 private final PaymentService delegate),而不是继承原始类。这带来两个直接好处:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 不侵入原类:AlipayService 不需要为日志或权限写一行新代码,也不用实现任何额外方法
- 支持任意叠加:new AuthPaymentDecorator(new LoggingPaymentDecorator(new AlipayService())) 能成立,正是因为每一层都遵守 PaymentService 接口,上层可把下层当“普通 PaymentService”来用
新增职责必须落在接口已有方法内
装饰器不能凭空添加新方法(比如加个 logError()),否则使用者必须强制转型才能调用,破坏了接口的统一性。正确做法是:
- 在
pay()方法内做增强:前置校验、后置记录、异常捕获并包装 - 若真需暴露新能力(如获取本次调用耗时),可考虑扩展接口本身(如新增
getMetrics()),但要评估是否所有实现都应支持;更稳妥的方式是用上下文对象(如传入Map<String, Object> context)或 ThreadLocal 携带附加信息
避免接口膨胀,保持聚焦
一个接口只定义核心职责。比如 DataSource 只管 readData() 和 writeData(),不要把压缩、加密、重试等都塞进去。这些交给对应的装饰器去实现:
- CompressingDataSource:在 write 前压缩,read 后解压
- RetryDataSource:在 write 失败时自动重试三次
这样,接口轻量稳定,职责扩展全由装饰器承担,改起来也互不影响。

















