Java 23 种设计模式:从踩坑到精通 | 番外:装饰器模式 —— 物流包裹增值服务实战
Java 23 种设计模式从踩坑到精通 | 番外装饰器模式 —— 物流包裹增值服务实战摘要装饰器模式通过“包装”的方式在不改变原有类的情况下动态地为对象添加功能支持多层嵌套和运行时组合是“组合优于继承”的经典范例。本文结合智能物流中“包裹增值服务保价/加急/易碎品包装/货到付款”的场景完整展示如何用装饰器模式灵活组合多种增值服务避免 5 种服务产生 31 个继承子类的爆炸问题并与外观模式深度对比帮你掌握“动态增强”的设计精髓。️本文阅读地图3 分钟速览为什么 5 种增值服务用继承会产生 31 个子类✅ 装饰器模式核心角色抽象构件、具体构件、抽象装饰器、具体装饰器手写包裹增值服务保价、加急、易碎品包装、货到付款任意组合 装饰器 vs 外观做加法 vs 做减法 面试必问“装饰器模式和代理模式有什么区别”《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 正篇装饰器模式 Decorator —— 比继承更灵活的扩展方式 当前番外 · 装饰器模式 × 物流包裹增值服务 返回系列总目录1. 物流增值服务的组合爆炸问题在智能物流系统中一个基础包裹可以叠加多种增值服务保价、加急、易碎品包装、货到付款…… 每种服务都会影响最终的描述和费用。如果为每种组合创建一个子类仅仅 5 种服务的组合就会产生 31 个子类。装饰器模式的解决思路用一系列包装器对象去“包裹”核心对象每个包装器在核心行为前后添加自己的功能再将调用转发给被包装对象。就像给包裹一层层加服务——先包装易碎品再保价再加急——每一层只增加自己的费用和描述。1.1 你的场景该不该用装饰器判断标准是 → 用装饰器否 → 用其他方式需要动态、透明地给对象添加功能✅❌功能可以任意组合且组合顺序可能影响结果✅❌不想用继承导致子类爆炸✅❌功能增强是固定的且不会动态变化❌直接修改类或使用继承只是想给对象加日志接口本身没变❌用 Lambda 函数式组合更轻量2. 装饰器模式 UML物流包裹增值服务场景3. 完整源码实现3.1 抽象构件物流包裹接口/** * 抽象构件物流包裹 * 定义包裹的基本行为接口 */publicinterfaceLogisticsPackage{StringgetDescription();doublegetCost();}白话所有包裹——无论是基础包裹还是加过保价、加急的包裹——都必须能“报描述”和“算费用”。3.2 具体构件基础包裹/** * 具体构件基础包裹 * 最基础的包裹实现提供默认描述和基础运费 */publicclassBasicPackageimplementsLogisticsPackage{privateStringdescription;privatedoublebaseCost;publicBasicPackage(Stringdescription,doublebaseCost){this.descriptiondescription;this.baseCostbaseCost;}OverridepublicStringgetDescription(){returndescription;}OverridepublicdoublegetCost(){returnbaseCost;}}白话这就是最原始的包裹——只有描述和基础运费。所有增值服务都是在这层基础上“包”上去的。3.3 抽象装饰器/** * 抽象装饰器包裹装饰器 * 持有 LogisticsPackage 引用实现与构件相同的接口 */publicabstractclassPackageDecoratorimplementsLogisticsPackage{protectedLogisticsPackagepkg;publicPackageDecorator(LogisticsPackagepkg){this.pkgpkg;}OverridepublicStringgetDescription(){returnpkg.getDescription();// 默认委托给被装饰对象}OverridepublicdoublegetCost(){returnpkg.getCost();// 默认委托给被装饰对象}}白话抽象装饰器同时实现了LogisticsPackage接口并持有一个LogisticsPackage引用——既是包裹又包装了另一个包裹。这就是装饰器能层层嵌套的关键。3.4 具体装饰器A保价服务/** * 具体装饰器A保价服务 * 按声明价值的百分比收取保价费 */publicclassInsuranceDecoratorextendsPackageDecorator{privatedoubledeclaredValue;privatestaticfinaldoubleINSURANCE_RATE0.03;publicInsuranceDecorator(LogisticsPackagepkg,doubledeclaredValue){super(pkg);this.declaredValuedeclaredValue;}OverridepublicStringgetDescription(){returnpkg.getDescription() 【保价服务】(声明价值: ¥declaredValue);}OverridepublicdoublegetCost(){returnpkg.getCost()declaredValue*INSURANCE_RATE;}}白话保价装饰器在被包装包裹的描述上追加保价信息费用上追加保价费。它不关心被包装的是基础包裹还是已经加过急的包裹——一视同仁。3.5 具体装饰器B加急服务/** * 具体装饰器B加急服务 */publicclassExpressDecoratorextendsPackageDecorator{privateExpressTypeexpressType;publicenumExpressType{NEXT_DAY(15.0),SAME_DAY(30.0);privatefinaldoublefee;ExpressType(doublefee){this.feefee;}publicdoublegetFee(){returnfee;}}publicExpressDecorator(LogisticsPackagepkg,ExpressTypeexpressType){super(pkg);this.expressTypeexpressType;}OverridepublicStringgetDescription(){returnpkg.getDescription() 【加急服务】(expressType);}OverridepublicdoublegetCost(){returnpkg.getCost()expressType.getFee();}}3.6 具体装饰器C易碎品包装/** * 具体装饰器C易碎品包装 */publicclassFragileDecoratorextendsPackageDecorator{privatestaticfinaldoubleFRAGILE_FEE8.0;publicFragileDecorator(LogisticsPackagepkg){super(pkg);}OverridepublicStringgetDescription(){returnpkg.getDescription() 【易碎品包装】(气泡膜防震填充);}OverridepublicdoublegetCost(){returnpkg.getCost()FRAGILE_FEE;}}3.7 具体装饰器D货到付款/** * 具体装饰器D货到付款 */publicclassCodDecoratorextendsPackageDecorator{privatedoublecodAmount;privatestaticfinaldoubleCOD_FEE_RATE0.02;privatestaticfinaldoubleMIN_COD_FEE5.0;publicCodDecorator(LogisticsPackagepkg,doublecodAmount){super(pkg);this.codAmountcodAmount;}OverridepublicStringgetDescription(){returnpkg.getDescription() 【货到付款】(代收金额: ¥codAmount);}OverridepublicdoublegetCost(){doublecodFeeMath.max(codAmount*COD_FEE_RATE,MIN_COD_FEE);returnpkg.getCost()codFee;}}3.8 客户端测试publicclassClient{publicstaticvoidmain(String[]args){System.out.println( 智能物流包裹增值服务系统装饰器模式\n);// 场景1普通包裹无增值服务System.out.println(【场景1】普通包裹 - 无增值服务);LogisticsPackagepkg1newBasicPackage(标准包裹北京→上海2kg,12.0);printInfo(pkg1);// 场景2保价 加急System.out.println(\n【场景2】保价 加急);LogisticsPackagepkg2newBasicPackage(标准包裹北京→广州1.5kg,15.0);pkg2newInsuranceDecorator(pkg2,5000.0);pkg2newExpressDecorator(pkg2,ExpressDecorator.ExpressType.NEXT_DAY);printInfo(pkg2);// 场景3易碎品 保价 加急当日达System.out.println(\n【场景3】易碎品 保价 加急当日达);LogisticsPackagepkg3newBasicPackage(标准包裹北京→深圳3kg,18.0);pkg3newFragileDecorator(pkg3);pkg3newInsuranceDecorator(pkg3,10000.0);pkg3newExpressDecorator(pkg3,ExpressDecorator.ExpressType.SAME_DAY);printInfo(pkg3);// 场景4货到付款 保价System.out.println(\n【场景4】货到付款 保价);LogisticsPackagepkg4newBasicPackage(标准包裹北京→杭州1kg,10.0);pkg4newCodDecorator(pkg4,800.0);pkg4newInsuranceDecorator(pkg4,800.0);printInfo(pkg4);// 场景5全都要System.out.println(\n【场景5】全都要易碎品 保价 加急 货到付款);LogisticsPackagepkg5newBasicPackage(标准包裹北京→成都5kg,25.0);pkg5newFragileDecorator(pkg5);pkg5newInsuranceDecorator(pkg5,15000.0);pkg5newExpressDecorator(pkg5,ExpressDecorator.ExpressType.NEXT_DAY);pkg5newCodDecorator(pkg5,2000.0);printInfo(pkg5);}privatestaticvoidprintInfo(LogisticsPackagepkg){System.out.println(-.repeat(70));System.out.println(pkg.getDescription());System.out.printf( 总费用¥%.2f\n,pkg.getCost());System.out.println(-.repeat(70));}}4. 运行结果 智能物流包裹增值服务系统装饰器模式 【场景1】普通包裹 - 无增值服务 ---------------------------------------------------------------------- 标准包裹北京→上海2kg 总费用¥12.00 ---------------------------------------------------------------------- 【场景2】保价 加急 ---------------------------------------------------------------------- 标准包裹北京→广州1.5kg 【保价服务】(声明价值: ¥5000.0) 【加急服务】(NEXT_DAY) 总费用¥177.00 ---------------------------------------------------------------------- 【场景3】易碎品 保价 加急当日达 ---------------------------------------------------------------------- 标准包裹北京→深圳3kg 【易碎品包装】 【保价服务】(声明价值: ¥10000.0) 【加急服务】(SAME_DAY) 总费用¥356.00 ---------------------------------------------------------------------- 【场景4】货到付款 保价 ---------------------------------------------------------------------- 标准包裹北京→杭州1kg 【货到付款】(代收金额: ¥800.0) 【保价服务】(声明价值: ¥800.0) 总费用¥50.00 ---------------------------------------------------------------------- 【场景5】全都要易碎品 保价 加急 货到付款 ---------------------------------------------------------------------- 标准包裹北京→成都5kg 【易碎品包装】 【保价服务】(声明价值: ¥15000.0) 【加急服务】(NEXT_DAY) 【货到付款】(代收金额: ¥2000.0) 总费用¥538.00 ----------------------------------------------------------------------5. 装饰器 vs 继承类的数量对比组合方式需要的子类数量仅 1 种服务4 选 14 个2 种服务组合6 个3 种服务组合4 个4 种服务全组合1 个总计继承方案15 个子类装饰器方案1 基础类 4 装饰器 5 个类 如果增值服务增加到 5 种继承方案需要 31 个子类而装饰器方案只需 6 个类。这就是“组合优于继承”的量化体现。6. 核心角色回顾角色职责对应代码Component定义对象的公共接口LogisticsPackageConcreteComponent被装饰的原始对象BasicPackageDecorator持有 Component 引用默认转发PackageDecoratorConcreteDecorator在转发前后添加自己的行为InsuranceDecorator等7. 装饰器模式 vs 外观模式对比项装饰器模式外观模式意图做加法动态扩展功能做减法简化调用入口接口不改变接口与构件完全一致提供全新的简化接口嵌套可层层嵌套自由组合通常一层不嵌套典型应用Java I/O 流、包裹增值服务SLF4J、JdbcTemplate一句话记忆装饰器是“加料师”——一层层加功能接口不变外观是“一键启动”——把复杂的东西简化成一个入口。BufferedInputStream给FileInputStream加缓冲是装饰器JdbcTemplate封装 JDBC 的复杂调用是外观。8. 装饰器模式的优缺点优点缺点动态扩展功能比继承更灵活产生大量小类增加代码复杂度遵循开闭原则新增装饰器无需修改原有类多层嵌套调试困难调用栈较深装饰器可任意组合实现不同功能组合依赖顺序某些组合对顺序敏感9. 六大设计原则体现原则体现单一职责每种装饰器只负责一种增强核心构件保持纯粹开闭原则新增增值服务只需新增装饰器类里氏替换装饰器与构件实现同一接口可相互替换依赖倒置客户端依赖抽象LogisticsPackage接口接口隔离LogisticsPackage接口精简只有两个方法迪米特法则客户端只知道LogisticsPackage接口不知内部包装层次附 装饰器模式 UML源码物流包裹增值服务场景startuml title Java 23 种设计模式从踩坑到精通 footer 折哥 | 智能物流与Java实战 1. 全局样式配置 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 2. 抽象构件 - 物流包裹 interface LogisticsPackage { getDescription() : String getCost() : double } note right of LogisticsPackage b抽象构件物流包裹/b -- 定义包裹的基本行为描述和费用 被装饰对象和装饰器都实现此接口 end note 3. 具体构件 - 基础包裹 class BasicPackage { - description : String - baseCost : double getDescription() : String getCost() : double } note right of BasicPackage b具体构件基础包裹/b -- 最基础的包裹实现 提供默认的描述和基础运费 end note 4. 抽象装饰器 abstract class PackageDecorator { - pkg : LogisticsPackage getDescription() : String getCost() : double } note right of PackageDecorator b抽象装饰器/b -- 持有 LogisticsPackage 引用 实现与构件相同的接口 默认委托给被装饰对象 end note 5. 具体装饰器 class InsuranceDecorator { getDescription() : String getCost() : double } note right of InsuranceDecorator b具体装饰器A保价服务/b -- 为包裹添加保价功能 费用 原费用 保价费 end note class ExpressDecorator { getDescription() : String getCost() : double } note right of ExpressDecorator b具体装饰器B加急服务/b -- 为包裹添加加急配送 费用 原费用 加急费 end note class FragileDecorator { getDescription() : String getCost() : double } note bottom of FragileDecorator b具体装饰器C易碎品包装/b -- 为包裹添加易碎品特殊包装 费用 原费用 包装费 end note class CodDecorator { getDescription() : String getCost() : double } note bottom of CodDecorator b具体装饰器D货到付款/b -- 为包裹添加代收货款服务 费用 原费用 手续费 end note 6. 关系连线 LogisticsPackage |.. BasicPackage : 实现 LogisticsPackage |.. PackageDecorator : 实现 PackageDecorator o-- LogisticsPackage : 包装/委托 PackageDecorator |-- InsuranceDecorator : 继承 PackageDecorator |-- ExpressDecorator : 继承 PackageDecorator |-- FragileDecorator : 继承 PackageDecorator |-- CodDecorator : 继承 enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录正篇装饰器模式 Decorator —— 比继承更灵活的扩展方式当前番外 · 装饰器模式 × 物流包裹增值服务你在这里创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通思路可鉴。

相关新闻

bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

Bootstrap RequireJS Director Knockout Web API 一个时髦的单页程序 在现代前端开发中,单页应用(SPA)已经成为主流。本文将实战演示如何利用 Bootstrap、RequireJS、Director、Knockout 和 Web API 构建一个时髦的单页程序。这些技术各…

2026/7/26 21:46:22 阅读更多 →
Desktop-Cube多显示器设置指南:解决X11与Wayland下的视角问题

Desktop-Cube多显示器设置指南:解决X11与Wayland下的视角问题

Desktop-Cube多显示器设置指南:解决X11与Wayland下的视角问题 【免费下载链接】Desktop-Cube 🧊 Indulge in nostalgia with useless 3D effects. 项目地址: https://gitcode.com/gh_mirrors/de/Desktop-Cube Desktop-Cube是一款能为Linux桌面环境…

2026/7/26 21:45:21 阅读更多 →
序列化陷阱:Protobuf与gRPC版本兼容性问题调试指南

序列化陷阱:Protobuf与gRPC版本兼容性问题调试指南

序列化问题的隐蔽性:一个Kafka反序列化失败案例 在微服务架构中,服务之间通过序列化协议交换数据。看似无关紧要的字段添加、枚举值变更,可能在生产环境中引发静默故障。考虑这样一个场景:订单服务向Kafka的orders.created主题发布事件,而履约服务消费该事件并将订单存入…

2026/7/26 21:45:21 阅读更多 →

最新新闻

OMAP4470与OMAP4460芯片差异解析:从Mailbox到调试支持的实战迁移指南

OMAP4470与OMAP4460芯片差异解析:从Mailbox到调试支持的实战迁移指南

1. 项目概述与核心价值在嵌入式系统开发,尤其是基于复杂SoC(片上系统)的产品设计中,硬件平台的每一次迭代都牵动着整个软件栈的神经。今天要深入探讨的,是德州仪器(TI)OMAP4系列中两款定位相近但…

2026/7/26 22:07:34 阅读更多 →
实测!MiniCPM-o-2_6-GPTQ与GPT-4o/Claude 3.5性能对比:8B参数如何超越巨头模型?

实测!MiniCPM-o-2_6-GPTQ与GPT-4o/Claude 3.5性能对比:8B参数如何超越巨头模型?

实测!MiniCPM-o-2_6-GPTQ与GPT-4o/Claude 3.5性能对比:8B参数如何超越巨头模型? 【免费下载链接】MiniCPM-o-2_6-GPTQ 项目地址: https://ai.gitcode.com/OpenBMB/MiniCPM-o-2_6-GPTQ MiniCPM-o-2_6-GPTQ是由OpenBMB开源社区推出的轻…

2026/7/26 22:07:34 阅读更多 →
RAG架构在企业知识库中的实践与优化

RAG架构在企业知识库中的实践与优化

1. 项目背景与核心价值去年帮某制造业客户搭建知识库时,他们内部有超过2万份技术文档,但工程师查找一个标准件参数平均要花15分钟。传统全文检索的准确率不到40%,直到我们引入RAG(检索增强生成)架构后,首次…

2026/7/26 22:07:34 阅读更多 →
CC2520 CCM*加密与关键寄存器配置实战指南

CC2520 CCM*加密与关键寄存器配置实战指南

1. 项目概述与核心价值在物联网和智能家居领域,Zigbee协议因其低功耗、自组网和高可靠性而备受青睐。作为这个生态系统的“末梢神经”,无线射频收发器的性能与安全性直接决定了整个网络的稳定与可信。TI的CC2520就是这样一款经典的2.4GHz IEEE 802.15.4/…

2026/7/26 22:07:34 阅读更多 →
Mage-Flow-Edit-Turbo:4B参数实现革命性图像编辑,比20B模型更快更高效

Mage-Flow-Edit-Turbo:4B参数实现革命性图像编辑,比20B模型更快更高效

Mage-Flow-Edit-Turbo:4B参数实现革命性图像编辑,比20B模型更快更高效 【免费下载链接】Mage-Flow-Edit-Turbo 项目地址: https://ai.gitcode.com/hf_mirrors/microsoft/Mage-Flow-Edit-Turbo Mage-Flow-Edit-Turbo是一款由微软开发的高效图像编…

2026/7/26 22:07:34 阅读更多 →
手把手教你调用Nemotron-3-Embed-1B-BF16-4bit API:查询/文档嵌入生成完整教程

手把手教你调用Nemotron-3-Embed-1B-BF16-4bit API:查询/文档嵌入生成完整教程

手把手教你调用Nemotron-3-Embed-1B-BF16-4bit API:查询/文档嵌入生成完整教程 【免费下载链接】Nemotron-3-Embed-1B-BF16-4bit 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Nemotron-3-Embed-1B-BF16-4bit Nemotron-3-Embed-1B-BF16-4bit…

2026/7/26 22:06:34 阅读更多 →

日新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

月新闻