主页 > 开源代码  > 

【设计模式】【结构型模式】装饰者模式(Decorator)

【设计模式】【结构型模式】装饰者模式(Decorator)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度++ 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 🎵 当你的天空突然下了大雨,那是我在为你炸乌云

文章目录 一、入门什么是装饰者模式?为什么要装饰者模式?怎样实现装饰者模式? 二、装饰者模式在框架源码中的实现Java I/O 流体系(最经典实现)Spring 框架中的装饰者应用 三、总结装饰者模式的优点装饰者模式的缺点装饰者模式的适用场景

一、入门 什么是装饰者模式?

装饰者模式(Decorator Pattern)是 Java 中常用的结构型设计模式,它能在不修改原有对象结构的前提下,动态地为对象添加额外的职责。

为什么要装饰者模式?

假设你正在开发一个电商系统,需要处理订单的 基础价格 和 多种附加服务(如快递加急、礼品包装、保价服务等),且这些附加服务可以任意组合。 下面是没有用装饰者模式的代码实现:

// 基础订单 class BasicOrder { /* 计算基础价格 */ } // 各种组合继承(产生大量重复代码) class BasicOrderWithExpress extends BasicOrder {} // 基础+快递 class BasicOrderWithGiftWrap extends BasicOrder {} // 基础+礼品 class BasicOrderWithExpressAndGiftWrap extends BasicOrder {} // 基础+快递+礼品 // ...更多组合(n种附加服务会产生2^n个子类!)

存在问题:

类数量指数级增长:3种附加服务需要7个子类,4种需要15个…代码重复严重:每个子类都要重写价格计算方法难以维护:新增一个附加服务(如保价),需要修改所有相关子类无法动态组合:运行时不能灵活增减服务 怎样实现装饰者模式?

装饰者模式由以下构成:

组件接口(Component):定义核心功能的抽象。定义被装饰对象和装饰器的共同行为规范,声明核心业务方法(如价格计算、服务描述),确保装饰过程的透明性(客户端无需区分原始对象和装饰后的对象)具体组件(ConcreteComponent):基础实现类。实现组件接口的基础功能,作为装饰过程的原始起点(最内层的被装饰对象),不应包含任何装饰逻辑装饰器基类(Decorator):持有组件引用,实现组件接口具体装饰器(ConcreteDecorator):添加具体增强功能

【案例】订单系统 - 改

组件接口:Order接口

interface Order { double calculatePrice(); String getDescription(); }

具体组件:基础订单,BasicOrder类

class BasicOrder implements Order { public double calculatePrice() { return 100.0; } // 基础价格100元 public String getDescription() { return "基础订单"; } }

装饰器基类:OrderDecorator类

// 装饰器基类(关键:实现相同接口) abstract class OrderDecorator implements Order { protected Order decoratedOrder; public OrderDecorator(Order order) { this.decoratedOrder = order; } // 默认直接转发给被装饰对象 public double calculatePrice() { return decoratedOrder.calculatePrice(); } public String getDescription() { return decoratedOrder.getDescription(); } }

具体装饰器:ExpressDecorator类(快递加急)、GiftWrapDecorator类(礼品包装)、InsuranceDecorator类(保价服务)

// 具体装饰器:快递加急 class ExpressDecorator extends OrderDecorator { public ExpressDecorator(Order order) { super(order); } public double calculatePrice() { return super.calculatePrice() + 25.0; // 加急费25元 } public String getDescription() { return super.getDescription() + " + 快递加急"; } } // 具体装饰器:礼品包装 class GiftWrapDecorator extends OrderDecorator { public GiftWrapDecorator(Order order) { super(order); } public double calculatePrice() { return super.calculatePrice() + 15.0; // 包装费15元 } public String getDescription() { return super.getDescription() + " + 礼品包装"; } } // 具体装饰器:保价服务 class InsuranceDecorator extends OrderDecorator { public InsuranceDecorator(Order order) { super(order); } public double calculatePrice() { return super.calculatePrice() + 30.0; // 保价费30元 } public String getDescription() { return super.getDescription() + " + 保价服务"; } }

客户端使用

public class Client { public static void main(String[] args) { // 基础订单 Order order = new BasicOrder(); // 动态叠加服务(可任意组合) order = new ExpressDecorator(order); // 加急 order = new GiftWrapDecorator(order); // 包装 order = new InsuranceDecorator(order); // 保价 System.out.println(order.getDescription()); // 输出:基础订单 + 快递加急 + 礼品包装 + 保价服务 System.out.println("总价:" + order.calculatePrice()); // 输出:总价:170.0 } } 二、装饰者模式在框架源码中的实现 Java I/O 流体系(最经典实现) InputStream in = new BufferedInputStream( // 具体装饰器 new FileInputStream( // 具体组件 new File("test.txt")));

源码中的实现: 组件接口(Component):InputStream抽象类。 具体组件(ConcreteComponent):FileInputStream类。 装饰器基类(Decorator):FilterInputStream类。 具体装饰器(ConcreteDecorator):BufferedInputStream类。

// 装饰器基类 FilterInputStream public class FilterInputStream extends InputStream { protected volatile InputStream in; // 持有被装饰对象 protected FilterInputStream(InputStream in) { this.in = in; } // 默认转发所有方法到被装饰对象 public int read() throws IOException { return in.read(); } } // 具体装饰器 BufferedInputStream public class BufferedInputStream extends FilterInputStream { private byte[] buf; // 新增缓冲区状态 public BufferedInputStream(InputStream in) { super(in); // 必须传入被装饰对象 buf = new byte[8192]; } // 增强的读取方法(实现缓冲机制) public int read() throws IOException { if (pos >= count) { fill(); // 装饰器新增的核心逻辑 if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; } } Spring 框架中的装饰者应用

这里说的比较简单,后续我学到Spring源码再补充😁 典型场景:事务缓存装饰器

// 装饰器基类实现 public class TransactionAwareCacheDecorator implements Cache { private final Cache targetCache; // 被装饰的缓存对象 public TransactionAwareCacheDecorator(Cache targetCache) { this.targetCache = targetCache; } // 在事务提交后才执行实际put操作 public void put(final Object key, final Object value) { TransactionSynchronizationManager.registerSynchronization( new TransactionSynchronizationAdapter() { public void afterCommit() { targetCache.put(key, value); } }); } } 装饰器注册:通过 CacheManager 包装原始缓存事务感知:延迟缓存操作到事务提交后与代理模式结合:常通过 AOP 动态应用装饰器 三、总结 装饰者模式的优点 动态扩展功能 无需修改原有代码,运行时动态添加功能案例:Java I/O 流中,BufferedInputStream 动态为 FileInputStream 添加缓冲功能 避免类爆炸 相比继承,装饰者模式通过组合实现功能扩展,避免子类数量指数级增长案例:电商订单系统中,3种附加服务只需3个装饰类,而不是7个子类 符合开闭原则 对扩展开放:新增装饰器不影响现有代码对修改封闭:无需修改组件接口和具体组件案例:Spring 的 TransactionAwareCacheDecorator 扩展缓存功能,不影响原有缓存实现 灵活组合 装饰器可以任意组合,实现不同功能叠加案例:Netty 的 ChannelPipeline 中,多个 ChannelHandler 可以按需组合 透明性 客户端无需区分原始对象和装饰后的对象案例:Java Collections 的 unmodifiableList 返回相同接口类型,对客户端透明 装饰者模式的缺点 复杂性增加 多层装饰可能导致调用链过长,增加调试和理解难度案例:Java I/O流中,多层装饰(如缓冲+字符集转换)可能让调用栈变深 装饰顺序敏感 不同装饰顺序可能导致不同结果案例:电商订单系统中,先加急再包装 vs 先包装再加急,价格计算可能不同 小对象增多 每个装饰器都是一个独立对象,可能增加内存开销案例:Netty 中,每个 ChannelHandler 都是一个独立装饰器 接口膨胀 组件接口需要定义所有装饰器可能用到的方法案例:Java I/O 中,InputStream 需要定义所有可能的流操作方法 不适合静态配置 如果功能组合是固定的,装饰者模式可能不如直接继承简洁案例:某些业务场景中,功能组合是固定的,直接继承更合适 装饰者模式的适用场景 动态功能扩展 需要运行时动态添加或撤销功能案例:Java I/O 流、电商订单附加服务 避免子类爆炸 功能组合复杂,继承会导致子类数量激增案例:游戏装备系统(武器+宝石+附魔) 透明增强 需要在不改变客户端代码的情况下增强功能案例:Spring 的 TransactionAwareCacheDecorator 分层处理 需要将功能拆分为多个独立模块,按需组合案例:Netty 的 ChannelPipeline、Web 中间件(权限校验→日志记录→缓存处理) 兼容性处理 需要在不修改原有代码的情况下适配新功能案例:Java Collections 的 checkedList 实现类型安全
标签:

【设计模式】【结构型模式】装饰者模式(Decorator)由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【设计模式】【结构型模式】装饰者模式(Decorator)