装饰器模式通过组合方式动态增强对象功能而不修改原代码。它用统一接口封装被装饰者与装饰器,支持运行时链式装配,如Java I/O流;遵循开闭原则,便于添加日志、重试等横切逻辑,且保持透明性与一致性。

包装设计模式(Wrapper Pattern),在 Java 中更常被称为装饰器模式(Decorator Pattern),它不修改原有类的代码,而是通过“包裹”一个已有对象,在其外层添加新行为或增强功能。这种方式比继承更灵活,也比修改源码更安全。
用组合代替继承,动态叠加功能
装饰器模式的核心是用组合关系替代继承关系。被装饰的对象和装饰器实现同一接口或继承同一抽象类,装饰器内部持有一个该类型对象的引用,并在方法调用前后插入逻辑。
- 比如
InputStream体系:原始的FileInputStream只能读字节;加上BufferedInputStream就有了缓冲能力;再套一层DataInputStream就能直接读int、boolean等基本类型 —— 每一层只关心自己的增强点,互不干扰。 - 关键在于所有装饰器和被装饰者都面向
InputStream编程,客户端无需知道具体是哪一层,调用方式完全一致。
遵循开闭原则,不改旧代码也能加新功能
当需要为某个类增加日志、权限校验、事务控制、缓存等横切关注点时,装饰器模式让你不用动原有类——只需写一个新的装饰器类,实现相同接口,在对应方法中加入额外逻辑,再委托给内部对象执行原操作。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 例如,给
PaymentService添加日志功能:写一个LoggingPaymentService,构造时传入真实的PaymentService实例;pay()方法里先打印日志,再调用内部实例的pay(),最后可再记录结果。 - 后续若还要加重试机制,就再写个
RetryPaymentService,它包装的是LoggingPaymentService,形成链式增强,原有代码一行都不用改。
支持运行时灵活装配,避免类爆炸
相比继承方式(如每种组合都要定义一个子类:BufferedAndDataInputStream、BufferedAndDataAndCipherInputStream……),装饰器允许在创建对象时按需组合:
立即学习“Java免费学习笔记(深入)”;
- new DataInputStream(new BufferedInputStream(new FileInputStream("a.txt")))
- 这种写法清晰表达了“先缓冲、再支持数据读取”的功能叠加顺序,也方便根据配置或条件决定是否启用某层装饰。
- 框架如 Spring AOP 的代理机制、Java I/O 类库、Guava 的集合工具类(如
ImmutableList包装器)都大量使用了这一思想。
注意装饰器的透明性与一致性
为了让装饰器真正“隐形”,必须保证:
- 装饰器类和被装饰类实现完全相同的公共接口(或抽象类),不能漏掉任何方法;
- 装饰器中的每个方法,原则上都应调用内部对象的对应方法(除非明确要拦截/替换);
- 避免在装饰器中暴露内部对象细节,否则会破坏封装,让调用方感知到层级结构。

















