Java 23 种设计模式:从踩坑到精通 | 番外:简单工厂模式 —— 物流计费策略实战
Java 23 种设计模式从踩坑到精通 | 番外简单工厂模式 —— 物流计费策略实战摘要简单工厂模式虽然不是 GoF 23 种设计模式之一但在实际开发中使用频率极高。它通过一个工厂类根据参数决定创建哪种具体产品让客户端无需直接new对象。本文结合智能物流中“根据订单类型创建不同计费策略”的场景完整展示简单工厂的实现并与工厂方法模式深度对比帮你掌握“参数化创建”的设计精髓。《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 正篇简单工厂模式 Factory —— 还在写一坨 if-else 创建对象吗 当前番外 · 简单工厂模式 × 物流计费策略 返回系列总目录1. 物流计费场景的痛点物流平台支持多种计费策略——标准件按“重量×距离”算加急件费率翻倍还要加服务费大件重货则按“首重续重”阶梯计费。如果每个订单服务都自己写计算逻辑代码会变成一坨if-elseif(standard.equals(type)){costweight*distance*0.5;}elseif(express.equals(type)){costweight*distance*0.5*250;}elseif(heavy.equals(type)){// 大件逻辑...}简单工厂的解决思路用一个工厂类封装所有策略的创建逻辑客户端只需传入类型参数即可拿到对应实例让创建与使用分离。2. 简单工厂 UML物流计费场景3. 完整源码实现3.1 抽象产品计费策略接口/** * 抽象产品计费策略接口 */publicinterfaceBillingStrategy{/** * 计算运费 * param weight 重量kg * param distance 距离km * return 运费金额 */doublecalculate(doubleweight,doubledistance);/** * 获取策略名称 */StringgetStrategyName();}白话所有计费方式都必须实现这个接口——能算运费能报名字。3.2 具体产品A标准计费策略/** * 具体产品A标准计费策略 */publicclassStandardBillingimplementsBillingStrategy{privatestaticfinaldoubleBASE_RATE0.5;// 每kg每km 0.5元Overridepublicdoublecalculate(doubleweight,doubledistance){returnweight*distance*BASE_RATE;}OverridepublicStringgetStrategyName(){return标准计费普通快递;}}白话标准件按“重量 × 距离 × 0.5”算简单直接。3.3 具体产品B加急计费策略/** * 具体产品B加急计费策略 */publicclassExpressBillingimplementsBillingStrategy{privatestaticfinaldoubleBASE_RATE0.5;privatestaticfinaldoubleEXPRESS_FEE50.0;// 加急服务费Overridepublicdoublecalculate(doubleweight,doubledistance){// 加急件基础费率×2 加急服务费returnweight*distance*BASE_RATE*2EXPRESS_FEE;}OverridepublicStringgetStrategyName(){return加急计费当日达/次日达;}}白话加急件费率翻倍还要加 50 元服务费。3.4 具体产品C大件计费策略/** * 具体产品C大件计费策略 */publicclassHeavyBillingimplementsBillingStrategy{privatestaticfinaldoubleFIRST_WEIGHT30.0;// 首重30kgprivatestaticfinaldoubleFIRST_RATE100.0;// 首重费用100元privatestaticfinaldoubleADDITIONAL_RATE2.0;// 续重每kg 2元Overridepublicdoublecalculate(doubleweight,doubledistance){if(weightFIRST_WEIGHT){returnFIRST_RATE;}returnFIRST_RATE(weight-FIRST_WEIGHT)*ADDITIONAL_RATE;}OverridepublicStringgetStrategyName(){return大件计费重货专线;}}白话大件按“首重 100 元 续重每 kg 2 元”算距离不参与计算重货专线统一价。3.5 简单工厂计费策略工厂importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;/** * 简单工厂计费策略工厂 * 根据类型参数创建对应的计费策略 */publicclassBillingStrategyFactory{// 使用缓存避免重复创建享元思想privatestaticfinalMapString,BillingStrategyCACHEnewConcurrentHashMap();static{// 预注册所有策略也可通过SPI动态加载CACHE.put(standard,newStandardBilling());CACHE.put(express,newExpressBilling());CACHE.put(heavy,newHeavyBilling());}/** * 工厂方法根据类型创建计费策略 * param type 策略类型standard / express / heavy * return 对应的计费策略实例 * throws IllegalArgumentException 不支持的类型 */publicstaticBillingStrategycreateStrategy(Stringtype){BillingStrategystrategyCACHE.get(type.toLowerCase());if(strategynull){thrownewIllegalArgumentException(不支持的计费策略类型type);}System.out.println([工厂] 创建计费策略 → strategy.getStrategyName());returnstrategy;}/** * 动态注册新的计费策略扩展用 */publicstaticvoidregisterStrategy(Stringtype,BillingStrategystrategy){CACHE.put(type.toLowerCase(),strategy);}}白话工厂预先缓存所有策略客户端要什么类型就从缓存取不用每次都new。新增策略可以调用registerStrategy动态注册。3.6 客户端订单服务/** * 客户端订单服务 */publicclassOrderService{/** * 创建订单并计算运费 */publicvoidcreateOrder(StringstrategyType,doubleweight,doubledistance){System.out.println(\n═.repeat(60));System.out.println(【创建订单】策略strategyType重量weightkg距离distancekm);System.out.println(═.repeat(60));// 通过简单工厂获取策略客户端不直接newBillingStrategystrategyBillingStrategyFactory.createStrategy(strategyType);// 计算运费doublecoststrategy.calculate(weight,distance);System.out.printf(计费策略%s\n,strategy.getStrategyName());System.out.printf(运费金额%.2f 元\n,cost);}}白话订单服务不关心用的是哪种计费策略它只管找工厂要、调calculate算钱。3.7 完整测试验证/** * 测试类验证简单工厂的创建与计算 */publicclassSimpleFactoryTest{publicstaticvoidmain(String[]args){System.out.println( 简单工厂模式物流计费策略 \n);OrderServiceorderServicenewOrderService();// 场景1标准件5kg200kmorderService.createOrder(standard,5,200);// 场景2加急件5kg200kmorderService.createOrder(express,5,200);// 场景3大件重货80kg200kmorderService.createOrder(heavy,80,200);// 验证不同策略类型是否返回不同实现System.out.println(\n═.repeat(60));System.out.println(【验证】不同策略类型返回不同实现);System.out.println(═.repeat(60));BillingStrategys1BillingStrategyFactory.createStrategy(standard);BillingStrategys2BillingStrategyFactory.createStrategy(express);BillingStrategys3BillingStrategyFactory.createStrategy(heavy);System.out.println(standard 实例类型s1.getClass().getSimpleName());System.out.println(express 实例类型s2.getClass().getSimpleName());System.out.println(heavy 实例类型s3.getClass().getSimpleName());}}4. 运行结果 简单工厂模式物流计费策略 ════════════════════════════════════════════════════════════ 【创建订单】策略standard重量5.0kg距离200.0km ════════════════════════════════════════════════════════════ [工厂] 创建计费策略 → 标准计费普通快递 计费策略标准计费普通快递 运费金额500.00 元 ════════════════════════════════════════════════════════════ 【创建订单】策略express重量5.0kg距离200.0km ════════════════════════════════════════════════════════════ [工厂] 创建计费策略 → 加急计费当日达/次日达 计费策略加急计费当日达/次日达 运费金额1050.00 元 ════════════════════════════════════════════════════════════ 【创建订单】策略heavy重量80.0kg距离200.0km ════════════════════════════════════════════════════════════ [工厂] 创建计费策略 → 大件计费重货专线 计费策略大件计费重货专线 运费金额200.00 元 ════════════════════════════════════════════════════════════ 【验证】不同策略类型返回不同实现 ════════════════════════════════════════════════════════════ [工厂] 创建计费策略 → 标准计费普通快递 [工厂] 创建计费策略 → 加急计费当日达/次日达 [工厂] 创建计费策略 → 大件计费重货专线 standard 实例类型StandardBilling express 实例类型ExpressBilling heavy 实例类型HeavyBilling5. 核心角色回顾角色职责对应代码Product定义产品的抽象接口BillingStrategyConcreteProduct实现具体产品StandardBilling/ExpressBilling/HeavyBillingSimpleFactory根据参数创建具体产品BillingStrategyFactoryClient调用工厂获取产品OrderService6. 简单工厂 vs 工厂方法对比项简单工厂工厂方法工厂结构一个具体工厂类抽象工厂接口 多个具体工厂创建方式静态方法通过参数判断子类重写工厂方法扩展性新增产品需修改工厂类违反OCP新增产品只需新增工厂子类符合OCP复杂度简单适合产品种类少的场景较复杂适合产品种类多且经常扩展的场景客户端依赖依赖具体工厂类只依赖抽象工厂接口7. 简单工厂的“坑”与优化问题解决方案违反开闭原则新增产品要改工厂结合反射 配置文件动态加载工厂类职责过重产品种类增多时升级为工厂方法静态方法难以 Mock 测试改为实例方法 依赖注入三者演进关系简单工厂参数判断→ 工厂方法子类决定→ 抽象工厂产品族是一个“从集中到分散、从单产品到产品族”的演进过程。8. 六大设计原则体现原则体现单一职责工厂只负责创建策略只负责计算开闭原则新增策略需修改工厂违反可结合反射优化里氏替换所有策略可替换BillingStrategy接口依赖倒置客户端依赖BillingStrategy抽象接口接口隔离BillingStrategy接口精简只有两个方法迪米特法则客户端只与工厂和策略接口交互简单工厂 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 BillingStrategy { double calculate(double weight, double distance) String getStrategyName() } note right of BillingStrategy b抽象产品Product/b -- 计费策略接口定义所有计费方式 的统一计算方法 end note 3. 具体产品A标准计费 class StandardBilling implements BillingStrategy { double calculate(double weight, double distance) String getStrategyName() } note right of StandardBilling b具体产品A/b -- 标准计费普通快递按重量×距离 基础费率计算 end note 4. 具体产品B加急计费 class ExpressBilling implements BillingStrategy { double calculate(double weight, double distance) String getStrategyName() } note right of ExpressBilling b具体产品B/b -- 加急计费加急件基础费率×2 加急服务费 end note 5. 具体产品C大件计费 class HeavyBilling implements BillingStrategy { double calculate(double weight, double distance) String getStrategyName() } note right of HeavyBilling b具体产品C/b -- 大件计费重货专线首重续重 阶梯式计费 end note 6. 简单工厂计费策略工厂 class BillingStrategyFactory { static BillingStrategy createStrategy(String type) - static final MapString, BillingStrategy CACHE } note right of BillingStrategyFactory b简单工厂SimpleFactory/b -- 根据传入的类型参数返回对应的 计费策略实例静态方法无需实例化 end note 7. 客户端 class OrderService { void createOrder(String strategyType, double weight, double distance) } note right of OrderService b客户端Client/b -- 只需传入策略类型无需关心 具体策略类的创建细节 end note 8. 关系连线 BillingStrategy |.. StandardBilling : 实现 BillingStrategy |.. ExpressBilling : 实现 BillingStrategy |.. HeavyBilling : 实现 BillingStrategyFactory .. BillingStrategy : 创建 OrderService .. BillingStrategyFactory : 调用 OrderService .. BillingStrategy : 使用 enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录正篇简单工厂模式 Factory —— 还在写一坨 if-else 创建对象吗当前番外 · 简单工厂模式 × 物流计费策略你在这里创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通思路可鉴。

相关新闻

“VLA-TVA”协同架构:打造具身智能“执行力”闭环(3)

“VLA-TVA”协同架构:打造具身智能“执行力”闭环(3)

前沿技术探索:AI智能体视觉(TVA,Transformer-based Vision Agent)是依托Transformer架构与“因式智能体”理论所构建的颠覆性工业视觉技术,是集深度强化学习(DRL)、卷积神经网络(CNN…

2026/7/23 21:31:58 阅读更多 →
【超详细】OpenClaw 2.7.9 Windows系统完整部署实操指南

【超详细】OpenClaw 2.7.9 Windows系统完整部署实操指南

📌 一、工具核心优势盘点 数据本地存储,安全系数高所有操作日志、文档资料均保存在本机,不会上传至云端,能够有效保护企业文件与个人隐私,规避数据泄露风险。 上手简单,零编程门槛采用全图形化可视化界面&…

2026/7/23 21:30:58 阅读更多 →
Alibaba Cloud Linux 3 On-premise Image

Alibaba Cloud Linux 3 On-premise Image

Alibaba Cloud Linux 3 On-premise Image

2026/7/23 21:30:58 阅读更多 →

最新新闻

IntelliJ IDEA 2026.2 最新发布

IntelliJ IDEA 2026.2 最新发布

IntelliJ IDEA 2026.2 已正式发布,带来了针对开发工作流与新技术的重大升级。 核心亮点包括原生集成 GitHub Copilot、新增 Logpoints 调试支持,以及对 Java 27 和 Kotlin 2.4 的首日支持。 发布日志可以参考官方的博文。 AI 的性能有些提升。 IntelliJ…

2026/7/23 21:38:00 阅读更多 →
2026梧州黄金回收白银回收铂金回收工商备案可查全城上门回收旧金老店联系方式推荐

2026梧州黄金回收白银回收铂金回收工商备案可查全城上门回收旧金老店联系方式推荐

2026梧州黄金白银铂金回收实测榜单|公安工商双备案无损测金无折旧费门店 梧州街头巷尾的贵金属回收店铺近年如雨后春笋般涌现,但不少市民反馈遭遇虚高报价、克扣损耗、未经同意熔金压价等消费陷阱。为帮助本地居民规避套路,小编实地走访全城&…

2026/7/23 21:38:00 阅读更多 →
网络一切正常但就是打不开某个特定网站,问题出在哪?

网络一切正常但就是打不开某个特定网站,问题出在哪?

浏览器里其他网页都能打开,就某一个打不开。刷新几次偶尔能加载出来,大部分时间卡住。ping能通,延迟也正常,浏览器里就是转圈。遇到这种情况,排查方向往往集中在“网站是不是挂了”。但换手机热点试一下又能打开&#…

2026/7/23 21:38:00 阅读更多 →
mybatisplus Enum枚举,@JsonValue / @JsonCreator简单使用

mybatisplus Enum枚举,@JsonValue / @JsonCreator简单使用

文章目录前言一、Enum定义1.完整代码2.分段解析1.状态定义2.状态内部变量定义3.构造函数4.重写getValue5.fromCodetips二、业务使用完整业务函数fromCode() 使用getValue()使用序列化和反序列化总结前言 Enum枚举类型安全、自带描述、支持 Mybatis 自动持久化、规范&#xff0…

2026/7/23 21:38:00 阅读更多 →
大规模感知模型:多模态情绪识别与动态反馈系统解析

大规模感知模型:多模态情绪识别与动态反馈系统解析

1. 大规模感知模型的核心机制解析大规模感知模型作为当前AI领域的前沿技术,其核心在于构建多模态情绪识别与动态反馈系统。这种模型通过整合文本语义分析、面部微表情识别、语音情感计算等多维度感知能力,实现对用户情绪状态的精准捕捉和量化评估。1.1 情…

2026/7/23 21:38:00 阅读更多 →
【剪映AI配音实战指南】:20年音视频专家亲授,3步搞定专业级AI配音(附避坑清单)

【剪映AI配音实战指南】:20年音视频专家亲授,3步搞定专业级AI配音(附避坑清单)

更多请点击: https://intelliparadigm.com 第一章:剪映AI配音的核心原理与技术演进 剪映AI配音并非简单的语音合成(TTS)工具,而是融合了端到端深度学习、音色克隆、韵律建模与上下文感知语音生成的多模态语音系统。其…

2026/7/23 21:37:00 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻