news 2026/5/14 4:33:17

策略模式如何替代if-else:从“面条代码”到Java面向对象的优雅转身

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
策略模式如何替代if-else:从“面条代码”到Java面向对象的优雅转身

写在前面

写业务代码时,最常见的“坏味道”就是满屏的if-else。判断用户类型、计算折扣、选择支付方式……每加一种新情况,就往if-else里塞一个分支。三个月后,这个函数动辄几百行,改一处怕崩十处。更可怕的是,不同分支里还夹杂着相似的逻辑,复制粘贴成了常态。这就是典型的面向过程思维写Java。今天我们要聊的策略模式,就是专门干掉if-else的利器。再配合工厂模式,连switch都不用手写。读完这篇,你将理解什么叫“对扩展开放,对修改关闭”,以及为什么说这才是真正的Java面向对象编程。

一、什么是策略模式?

策略模式(Strategy Pattern)定义了一系列算法(或业务规则),将每个算法封装起来,并使它们可以相互替换。策略模式让算法的变化独立于使用它的客户端。

核心角色

  • 策略接口(Strategy):定义所有策略的公共方法。

  • 具体策略(ConcreteStrategy):实现策略接口,封装具体算法或规则。

  • 上下文(Context):持有策略对象的引用,负责调用策略。

二、为什么需要策略模式?——一个if-else的反面案例

假设我们有一个计算订单折扣的功能:

public double calculateDiscount(String userLevel, double amount) { if ("VIP".equals(userLevel)) { return amount * 0.8; // VIP 8折 } else if ("GOLD".equals(userLevel)) { return amount * 0.9; // 黄金 9折 } else if ("SILVER".equals(userLevel)) { return amount * 0.95; // 白银 95折 } else { return amount; // 普通无折扣 } }

痛点

  1. 每增加一种用户等级,就要修改这个函数,违反开闭原则

  2. 折扣算法可能在其他地方复用,只能复制粘贴。

  3. 单元测试需要覆盖所有分支,复杂且易遗漏。

  4. 多个if-else嵌套时,代码可读性极差。

策略模式的解决方案:将每种折扣算法封装成独立的策略类,客户端根据需要选择策略。

三、策略模式的代码实现(Java)

3.1 定义策略接口

java

public interface DiscountStrategy { double calculate(double amount); }

3.2 实现具体策略

public class VipDiscountStrategy implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.8; } } public class GoldDiscountStrategy implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.9; } } public class SilverDiscountStrategy implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.95; } } public class RegularDiscountStrategy implements DiscountStrategy { @Override public double calculate(double amount) { return amount; } }

3.3 上下文类

public class OrderContext { private DiscountStrategy strategy; public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; } public double calculateDiscount(double amount) { return strategy.calculate(amount); } }

3.4 客户端使用

public class Client { public static void main(String[] args) { OrderContext order = new OrderContext(); // VIP用户 order.setStrategy(new VipDiscountStrategy()); System.out.println(order.calculateDiscount(100)); // 80.0 // 黄金用户 order.setStrategy(new GoldDiscountStrategy()); System.out.println(order.calculateDiscount(100)); // 90.0 } }

问题:客户端仍然需要知道具体策略类并手动创建。这没有完全消除if-else——客户端还得判断等级然后new对应的策略。如何解决?引入工厂模式

四、为什么要引入工厂模式?

工厂模式负责根据条件创建对应的策略对象,将“选择哪个策略”的逻辑集中到工厂中,客户端只需传入标识(如字符串、枚举),工厂返回策略实例。

4.1 简单工厂 + 策略模式

public class DiscountStrategyFactory { public static DiscountStrategy getStrategy(String userLevel) { switch (userLevel) { case "VIP": return new VipDiscountStrategy(); case "GOLD": return new GoldDiscountStrategy(); case "SILVER": return new SilverDiscountStrategy(); default: return new RegularDiscountStrategy(); } } }

客户端变为:

String level = "VIP"; DiscountStrategy strategy = DiscountStrategyFactory.getStrategy(level); order.setStrategy(strategy);

依然有switch,但至少集中在一处。进一步优化:使用注册表 + 反射消除switch

4.2 使用Map注册策略(推荐)

public class DiscountStrategyFactory { private static final Map<String, DiscountStrategy> strategies = new HashMap<>(); static { strategies.put("VIP", new VipDiscountStrategy()); strategies.put("GOLD", new GoldDiscountStrategy()); strategies.put("SILVER", new SilverDiscountStrategy()); strategies.put("REGULAR", new RegularDiscountStrategy()); } public static DiscountStrategy getStrategy(String userLevel) { return strategies.getOrDefault(userLevel, strategies.get("REGULAR")); } }

这样,新增策略只需在Map中添加一行,无需修改工厂逻辑。完美符合开闭原则

五、策略模式+工厂模式 = Java面向对象的极致体现

组合之后,架构清晰:

为什么说这是面向对象的体现?

  1. 封装:每个策略算法独立封装,互不影响。

  2. 继承/多态:策略接口统一,具体策略通过多态实现。

  3. 开闭原则:新增策略无需修改原有代码,只需添加新类+注册。

  4. 单一职责:每个策略类只负责一种算法;工厂只负责创建;上下文只负责委托。

六、实战:替换RAG系统中的if-else

在你的RAG项目中,可能需要对不同文档类型(PDF、Word、Markdown)采用不同的切分策略。用if-else

if ("pdf".equals(type)) { return parsePdf(file); } else if ("docx".equals(type)) { return parseDocx(file); } else if ("md".equals(type)) { return parseMd(file); }

改用策略+工厂

// 策略接口 public interface ParseStrategy { List<String> parse(File file); } // 具体策略 public class PdfParseStrategy implements ParseStrategy { ... } public class DocxParseStrategy implements ParseStrategy { ... } // 工厂 public class ParseStrategyFactory { private static final Map<String, ParseStrategy> map = new HashMap<>(); static { map.put("pdf", new PdfParseStrategy()); map.put("docx", new DocxParseStrategy()); map.put("md", new MdParseStrategy()); } public static ParseStrategy getStrategy(String type) { return map.get(type); } } // 使用 ParseStrategy strategy = ParseStrategyFactory.getStrategy(fileType); List<String> chunks = strategy.parse(file);

从此,新增一种文档格式只需写新的策略类并在工厂注册一行。原有代码纹丝不动。

七、总结

  • 策略模式:将算法封装成独立类,消除条件分支。

  • 工厂模式:负责创建策略对象,解耦客户端与具体策略。

  • 组合使用:既消灭了if-else,又实现了开闭原则,是Java面向对象编程的经典实践。

下次当你看到超过3个if-else分支时,就该考虑重构为策略模式了。写出的代码将更易读、易测、易扩展。

你的项目中还有哪些地方被if-elseswitch支配着?试着用策略模式重构一下,看看代码减少了多少行?或者你遇到过策略类过多导致工厂膨胀的问题吗?欢迎分享你的重构经验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 4:31:05

BAT_interviews快速入门:3天掌握BAT面试核心知识点

BAT_interviews快速入门&#xff1a;3天掌握BAT面试核心知识点 【免费下载链接】BAT_interviews 项目地址: https://gitcode.com/gh_mirrors/ba/BAT_interviews BAT_interviews是一个全面的面试准备项目&#xff0c;汇集了阿里巴巴、百度、腾讯等知名企业的面试题及答案…

作者头像 李华
网站建设 2026/5/14 4:29:13

终极指南:3分钟学会用Video-subtitle-extractor高效提取视频硬字幕

终极指南&#xff1a;3分钟学会用Video-subtitle-extractor高效提取视频硬字幕 【免费下载链接】video-subtitle-extractor 视频硬字幕提取&#xff0c;生成srt文件。无需申请第三方API&#xff0c;本地实现文本识别。基于深度学习的视频字幕提取框架&#xff0c;包含字幕区域检…

作者头像 李华
网站建设 2026/5/14 4:26:03

如何构建可靠的GKD第三方订阅管理系统:从数据规范到自动化验证

如何构建可靠的GKD第三方订阅管理系统&#xff1a;从数据规范到自动化验证 【免费下载链接】GKD_THS_List GKD第三方订阅收录名单 项目地址: https://gitcode.com/gh_mirrors/gk/GKD_THS_List 在Android自动化生态中&#xff0c;GKD订阅管理是一个关键但常被忽视的环节。…

作者头像 李华
网站建设 2026/5/14 4:25:08

10分钟打造高性能Nginx服务器:server-configs-nginx完整配置指南

10分钟打造高性能Nginx服务器&#xff1a;server-configs-nginx完整配置指南 【免费下载链接】server-configs-nginx Nginx HTTP server boilerplate configs 项目地址: https://gitcode.com/gh_mirrors/se/server-configs-nginx GitHub 加速计划的 se/server-configs-n…

作者头像 李华
网站建设 2026/5/14 4:20:22

PyMatting Laplacian矩阵详解:图像抠图的数学原理与实现指南

PyMatting Laplacian矩阵详解&#xff1a;图像抠图的数学原理与实现指南 【免费下载链接】pymatting A Python library for alpha matting 项目地址: https://gitcode.com/gh_mirrors/py/pymatting 图像抠图技术在现代数字图像处理中扮演着至关重要的角色&#xff0c;而…

作者头像 李华
网站建设 2026/5/14 4:20:20

长序列LLM服务的稀疏注意力机制优化与实践

1. 长序列LLM服务的挑战与稀疏注意力机制在自然语言处理领域&#xff0c;处理长序列输入一直是大语言模型&#xff08;LLM&#xff09;服务面临的核心挑战。传统Transformer架构的自注意力机制计算复杂度随序列长度呈平方级增长&#xff0c;当处理64k tokens以上的长文档时&…

作者头像 李华