java中无原生装饰器语法糖,但可通过接口+组合实现:定义component接口、concretecomponent实现类、decorator抽象类(持委托对象),再创建logging/ auth装饰器链式叠加,顺序决定执行流程。

Java 中没有原生的“装饰器模式”语法糖(不像 Python 的 @decorator),但可以通过面向对象设计实现经典的装饰器模式——用包装类(wrapper)在运行时动态增强对象行为,完全不修改原始类代码。
核心思路:用接口统一行为,用组合代替继承
装饰器模式依赖三个关键角色:
- 组件接口(Component):定义被装饰对象和装饰器共同遵守的行为契约
- 具体组件(ConcreteComponent):原始业务类,只关注核心逻辑
- 装饰器抽象类(Decorator):持有 Component 引用,并实现相同接口;子类在此基础上添加新功能
所有装饰器都遵循“包装 + 委托 + 增强”的结构:构造时接收被装饰对象,调用方法时先执行自身逻辑,再委托给内部对象(或前后都增强)。
写一个可叠加的日志+权限校验装饰器
假设有一个 PaymentService 接口和其实现类 AlipayService:
interface PaymentService {
void pay(double amount);
}
class AlipayService implements PaymentService {
public void pay(double amount) {
System.out.println("支付宝支付 " + amount + " 元");
}
}
现在想动态加日志和权限检查,不改 AlipayService 一行代码:
- 定义抽象装饰器:
abstract class PaymentDecorator implements PaymentService,含 protected 成员private final PaymentService delegate; - 日志装饰器:
class LoggingPaymentDecorator extends PaymentDecorator,在pay()前后打印时间戳和结果 - 权限装饰器:
class AuthPaymentDecorator extends PaymentDecorator,在pay()前校验用户角色,失败则抛异常
使用时链式组合:new AuthPaymentDecorator(new LoggingPaymentDecorator(new AlipayService()))。顺序决定执行流程(比如先鉴权再记日志)。
注意边界与常见陷阱
装饰器不是万能的,用错容易引入问题:
- 避免过度嵌套:5 层以上装饰器会让调用栈变深、调试困难;考虑是否该提取为策略或责任链
- 装饰器必须实现相同接口:不能新增方法(否则使用者需强制转型),如需扩展能力,可定义更宽泛接口或配合其他模式(如观察者)
- 状态管理要谨慎:装饰器本身不应保存影响被装饰对象状态的数据;若需共享上下文(如请求 ID),可通过 ThreadLocal 或传参方式传递
- 不可装饰 final 类或方法:Java 动态代理可绕过此限制,但那是另一种实现路径(基于接口的 JDK Proxy 或 CGLIB)
对比动态代理:什么时候选哪种?
装饰器模式适用于编译期已知、逻辑明确、可复用的增强逻辑(如日志、缓存、重试)。而 JDK 动态代理更适合横切关注点集中、需统一拦截多个类多个方法的场景(如 Spring AOP)。前者是手动组合、类型安全;后者是运行时织入、配置驱动。两者不互斥——你完全可以写一个通用 LoggingInvocationHandler,再把它包装成符合某接口的装饰器。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











