news 2026/5/14 17:31:13

策略模式:告别 if-else 地狱,让代码优雅到飞起

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
策略模式:告别 if-else 地狱,让代码优雅到飞起

策略模式(Strategy Pattern)

一句话理解

策略模式 = “interchangeable algorithms”,定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。

就像去餐厅,你可以选择微信支付、支付宝、刷卡,不同的支付方式就是不同的"策略"。


【核心思想】

把不同的算法/行为封装成独立的类,让它们可以互相替换。

客户端不需要知道具体使用哪个算法,只需要调用统一的接口。


【为什么要用策略模式?】

❌ 不用策略模式时,代码是这样的:

publicclassPaymentService{publicvoidpay(Stringtype,BigDecimalamount){if("alipay".equals(type)){// 支付宝支付逻辑(50行代码)System.out.println("支付宝支付...");}elseif("wechat".equals(type)){// 微信支付逻辑(50行代码)System.out.println("微信支付...");}elseif("bank".equals(type)){// 银行卡支付逻辑(50行代码)System.out.println("银行卡支付...");}// 每加一种支付方式,这里就要加一堆 if-else// 类越来越臃肿,修改一个支付方式可能影响其他方式// 老板:再加个云闪付!// 你:又要改这个类... 😭}}

✅ 使用策略模式后:

// 每种支付方式一个类,独立维护// 新增支付方式?新建一个类就行!// 修改某个支付方式?只改对应的类!// 老板:再加个云闪付!// 你:淡定新建一个类 😎

【代码结构图解】

┌─────────────────────────────────────────────────────────────────┐ │ 上下文 (Context) │ │ PaymentContext │ │ ┌─────────────────────────────────────────┐ │ │ │ setStrategy(PaymentStrategy strategy) │ │ │ │ executePay(BigDecimal amount) │ │ │ │ → strategy.pay(amount) │ │ │ └─────────────────────────────────────────┘ │ └───────────────────────────┬─────────────────────────────────────┘ │ ▼ 持有策略接口 ┌─────────────────────────────────────────────────────────────────┐ │ 策略接口 (Strategy) │ │ PaymentStrategy │ │ ┌─────────────────────────────────────────┐ │ │ │ pay(BigDecimal amount) │ │ │ │ calculateFee(BigDecimal amount) │ │ │ └─────────────────────────────────────────┘ │ └───────────────────────────┬─────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ AlipayStrategy │ │ WechatStrategy │ │ BankStrategy │ │ 支付宝策略 │ │ 微信策略 │ │ 银行卡策略 │ │ │ │ │ │ │ │ pay() │ │ pay() │ │ pay() │ │ 0.6%手续费 │ │ 0.5%手续费 │ │ 固定2元 │ └────────────────┘ └────────────────┘ └────────────────┘

【核心代码示例 - 支付系统】

1️⃣ 定义策略接口

// 支付策略接口publicinterfacePaymentStrategy{// 支付voidpay(BigDecimalamount);// 计算手续费BigDecimalcalculateFee(BigDecimalamount);// 验证booleanvalidate();}

2️⃣ 具体策略实现

🔷 支付宝支付策略
publicclassAlipayStrategyimplementsPaymentStrategy{@Overridepublicvoidpay(BigDecimalamount){System.out.println("【支付宝】支付金额:"+amount+"元");System.out.println("【支付宝】调用支付宝SDK...");System.out.println("【支付宝】正在刷脸...");System.out.println("【支付宝】支付成功!花呗额度-"+amount);}@OverridepublicBigDecimalcalculateFee(BigDecimalamount){// 支付宝手续费 0.6%,马爸爸要恰饭的嘛returnamount.multiply(newBigDecimal("0.006"));}@Overridepublicbooleanvalidate(){System.out.println("【支付宝】验证账户余额...");System.out.println("【支付宝】余额不足,自动切换花呗!");returntrue;}}
🟢 微信支付策略
publicclassWechatPayStrategyimplementsPaymentStrategy{@Overridepublicvoidpay(BigDecimalamount){System.out.println("【微信支付】支付金额:"+amount+"元");System.out.println("【微信支付】调用微信SDK...");System.out.println("【微信支付】正在加载小程序...");System.out.println("【微信支付】支付成功!零钱-"+amount);}@OverridepublicBigDecimalcalculateFee(BigDecimalamount){// 微信手续费 0.5%,比支付宝良心一点点returnamount.multiply(newBigDecimal("0.005"));}@Overridepublicbooleanvalidate(){System.out.println("【微信支付】验证微信账户...");System.out.println("【微信支付】检测到你是尊贵的VIP用户!");returntrue;}}
🟡 银行卡支付策略
publicclassBankCardStrategyimplementsPaymentStrategy{@Overridepublicvoidpay(BigDecimalamount){System.out.println("【银行卡】支付金额:"+amount+"元");System.out.println("【银行卡】调用银联接口...");System.out.println("【银行卡】正在连接银行服务器...");System.out.println("【银行卡】支付成功!余额-"+amount);System.out.println("【银行卡】短信通知已发送至您的手机");}@OverridepublicBigDecimalcalculateFee(BigDecimalamount){// 银行卡固定手续费 2元,不管你买1块还是1万,都是2块// 买1块钱的东西血亏 😂returnnewBigDecimal("2");}@Overridepublicbooleanvalidate(){System.out.println("【银行卡】验证卡号和密码...");System.out.println("【银行卡】正在发送验证码到138****8888...");System.out.println("【银行卡】验证码输入超时,请重新获取!");System.out.println("【银行卡】开玩笑的,验证通过了~");returntrue;}}

3️⃣ 上下文类(使用策略)

// 支付上下文publicclassPaymentContext{privatePaymentStrategystrategy;// 设置策略(可以在构造时或运行时设置)publicvoidsetStrategy(PaymentStrategystrategy){this.strategy=strategy;}// 执行支付publicvoidexecutePay(BigDecimalamount){if(strategy==null){thrownewIllegalStateException("请先设置支付方式");}// 1. 验证if(strategy.validate()){// 2. 计算手续费BigDecimalfee=strategy.calculateFee(amount);BigDecimaltotal=amount.add(fee);System.out.println("\n========== 支付详情 ==========");System.out.println("商品金额:"+amount+"元");System.out.println("手续费:"+fee+"元");System.out.println("应付总额:"+total+"元");System.out.println("==============================\n");// 3. 执行支付strategy.pay(total);}else{System.out.println("支付验证失败!");}}}

4️⃣ 客户端使用

publicclassOrderService{publicvoidcheckout(StringpayType,BigDecimalamount){PaymentContextcontext=newPaymentContext();// 根据支付方式选择策略switch(payType){case"alipay":context.setStrategy(newAlipayStrategy());break;case"wechat":context.setStrategy(newWechatPayStrategy());break;case"bank":context.setStrategy(newBankCardStrategy());break;default:thrownewIllegalArgumentException("不支持的支付方式:"+payType);}// 执行支付(不需要知道具体用哪个策略)context.executePay(amount);}}

使用示例:

OrderServiceservice=newOrderService();service.checkout("alipay",newBigDecimal("100"));// 支付宝支付service.checkout("wechat",newBigDecimal("100"));// 微信支付service.checkout("bank",newBigDecimal("100"));// 银行卡支付

【策略模式的优缺点】

✅ 优点:

优点说明
算法/行为独立易于切换、理解和扩展
避免使用多重条件判断告别 if-else 地狱
每个策略独立封装修改不影响其他策略
符合开闭原则新增策略只需新增类
老板改需求时你可以淡定地说:“就改一个类” 😏

❌ 缺点:

缺点说明
策略类数量增多每个策略一个类
客户端必须知道所有策略类并自行决定使用哪一个
策略之间可能会有重复代码可以用组合优化
类多了,找起来有点费劲IDE:你在教我做事?

【适用场景】

✅ 适合用:

  • 系统需要动态地在几种算法中选择一种
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句出现
  • 需要隐藏复杂的算法/数据结构
  • 一个类中的大量代码依赖于某个条件,比如类型

❌ 不适合:

  • 策略数量很少(1-2个),没必要搞这么复杂
  • 策略之间差异极小,可以合并

【常见应用场景】

  1. 💰支付方式选择(支付宝/微信/银行卡)
  2. 🎁促销活动计算(满减/折扣/秒杀)
  3. 📊排序算法选择(快速排序/归并排序/冒泡排序)
  4. 📄文件导出格式(PDF/Excel/Word)
  5. 📱消息发送渠道(短信/邮件/推送)
  6. 👑会员等级计算(普通/VIP/SVIP)

【使用口诀】

🎯 算法行为多又杂,
🎯 策略模式来帮忙。
🎯 每个算法一个类,
🎯 随意切换真方便!
🎯 告别 if-else 地狱,
🎯 代码清爽不抓狂!


【和工厂模式的区别】

对比工厂模式策略模式
关注重点对象的创建行为的封装
核心目的解耦对象创建解耦算法使用
使用方式factory.create()strategy.do()
经典组合可以一起用!工厂创建策略

二、工厂模式 + 策略模式

一句话理解

工厂模式负责"创建策略对象",策略模式负责"执行算法"。

两者结合 = 创建与使用的完美解耦,代码优雅到飞起!


【为什么要组合使用?】

❌ 只用策略模式,客户端代码是这样的:

publicclassOrderService{publicvoidcheckout(StringpayType,BigDecimalamount){PaymentContextcontext=newPaymentContext();// 客户端需要知道所有策略类,还要自己判断用哪个// 每加一种支付方式,这里就要改一次!switch(payType){case"alipay":context.setStrategy(newAlipayStrategy());// 直接 new,耦合!break;case"wechat":context.setStrategy(newWechatPayStrategy());break;case"bank":context.setStrategy(newBankCardStrategy());break;// 老板:再加个云闪付!// 你:又要改客户端代码... 😭}context.executePay(amount);}}

✅ 工厂+策略组合,客户端代码变成这样:

publicclassOrderService{publicvoidcheckout(StringpayType,BigDecimalamount){PaymentContextcontext=newPaymentContext();// 一行代码搞定!工厂帮我创建策略!context.setStrategy(PaymentStrategyFactory.getStrategy(payType));context.executePay(amount);}}// 老板:再加个云闪付!// 你:只改工厂,客户端代码不动!😎

【组合使用的核心好处】

好处说明
彻底解耦客户端不依赖任何具体策略类,只依赖接口
开闭原则新增策略只需:1.新建策略类 2.注册到工厂
代码复用工厂可以全局复用,避免到处 new
易于测试可以 mock 工厂返回的策略,方便单元测试
配置化策略类型可以写在配置文件里,不用改代码

【代码结构图解】

┌─────────────────────────────────────────────────────────────────┐ │ 客户端 (Client) │ │ OrderService │ │ │ │ // 客户端只认识工厂和接口,不认识具体策略! │ │ strategy = PaymentStrategyFactory.getStrategy("alipay") │ │ context.setStrategy(strategy) │ │ context.executePay(amount) │ │ │ └───────────────────────────┬─────────────────────────────────────┘ │ ▼ 工厂创建策略 ┌─────────────────────────────────────────────────────────────────┐ │ 工厂 (PaymentStrategyFactory) │ │ │ │ Map<String, PaymentStrategy> │ │ ├─ "alipay" → new AlipayStrategy() │ │ ├─ "wechat" → new WechatPayStrategy() │ │ ├─ "bank" → new BankCardStrategy() │ │ └─ "union" → new UnionPayStrategy() ← 新增只需加这一行! │ │ │ │ getStrategy(String type) → 返回对应策略 │ │ │ └───────────────────────────┬─────────────────────────────────────┘ │ ▼ 返回策略对象 ┌─────────────────────────────────────────────────────────────────┐ │ 上下文 (PaymentContext) │ │ │ │ setStrategy(PaymentStrategy strategy) │ │ executePay(BigDecimal amount) { │ │ strategy.validate(); │ │ strategy.calculateFee(amount); │ │ strategy.pay(amount); │ │ } │ │ │ └───────────────────────────┬─────────────────────────────────────┘ │ ▼ 调用策略方法 ┌─────────────────────────────────────────────────────────────────┐ │ 具体策略 (Concrete Strategies) │ │ │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ │ │ │ AlipayStrategy │ │ WechatPayStrategy│ │ BankStrategy │ │ │ │ 支付宝策略 │ │ 微信策略 │ │ 银行卡策略 │ │ │ └──────────────────┘ └──────────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘

【工厂 + 策略 代码实现】

1️⃣ 策略工厂类

publicclassPaymentStrategyFactory{// 用一个 Map 缓存所有策略,避免重复创建privatestaticfinalMap<String,PaymentStrategy>STRATEGY_MAP=newHashMap<>();// 静态代码块,初始化所有策略static{STRATEGY_MAP.put("alipay",newAlipayStrategy());STRATEGY_MAP.put("wechat",newWechatPayStrategy());STRATEGY_MAP.put("bank",newBankCardStrategy());// 老板:再加个云闪付!// 你:只加这一行就行!😎// STRATEGY_MAP.put("union", new UnionPayStrategy());}/** * 根据支付类型获取对应策略 * @param payType 支付类型 * @return 支付策略 */publicstaticPaymentStrategygetStrategy(StringpayType){PaymentStrategystrategy=STRATEGY_MAP.get(payType);if(strategy==null){thrownewIllegalArgumentException("不支持的支付方式:"+payType);}returnstrategy;}/** * 获取所有支持的支付方式(方便前端展示) */publicstaticSet<String>getAllPayTypes(){returnSTRATEGY_MAP.keySet();}}

2️⃣ 优化后的客户端代码

@ServicepublicclassOrderService{@AutowiredprivatePaymentContextpaymentContext;/** * 结账 - 工厂+策略模式版本 * 客户端代码简洁到令人发指! */publicvoidcheckout(StringpayType,BigDecimalamount){// 一行代码搞定!工厂帮我创建策略!PaymentStrategystrategy=PaymentStrategyFactory.getStrategy(payType);// 设置策略并执行paymentContext.setStrategy(strategy);paymentContext.executePay(amount);}}

3️⃣ Spring Boot 实战版本

@ConfigurationpublicclassStrategyConfig{/** * 将策略注册为 Spring Bean,方便管理和扩展 */@BeanpublicMap<String,PaymentStrategy>paymentStrategies(AlipayStrategyalipayStrategy,WechatPayStrategywechatStrategy,BankCardStrategybankStrategy){Map<String,PaymentStrategy>strategies=newHashMap<>();strategies.put("alipay",alipayStrategy);strategies.put("wechat",wechatStrategy);strategies.put("bank",bankStrategy);returnstrategies;}}@ServicepublicclassPaymentService{@AutowiredprivateMap<String,PaymentStrategy>strategies;@AutowiredprivatePaymentContextcontext;publicvoidpay(StringpayType,BigDecimalamount){PaymentStrategystrategy=strategies.get(payType);if(strategy==null){thrownewBusinessException("不支持的支付方式");}context.setStrategy(strategy);context.executePay(amount);}}

4️⃣ 对比总结

场景纯策略模式工厂+策略模式
新增支付方式改客户端代码 😭只改工厂 😎
客户端代码又长又臭一行搞定
耦合度高(直接 new)低(工厂创建)
可测试性难 mock易 mock
配置化不支持支持 YAML/DB 配置

💡温馨提示:策略模式 + 工厂模式是实际项目中的黄金搭档,既能解耦算法,又能解耦对象的创建,强烈推荐在实际项目中使用!


📌写文不易,Bug 更不易。

如果这篇文章对你有帮助,可以搜一搜:空门技术栈

https://mp.weixin.qq.com/s/v4JI6UnfQldz2R9b_GfxGQ

推荐阅读

写 Java 别只会 new:工厂模式,才是对象界的正规军!

这里分享:

  • ✅ Java / Spring AI / 企业级项目实战
  • ✅ Docker / RAG知识库 / 微服务踩坑
  • ✅ Python、前端、AI应用落地
  • ✅ 偶尔分享一些「头发保卫战」经验 😆

一个热爱技术、持续填坑的开发者,
陪你一起少踩坑,少加班,多写优雅代码。

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

Midscene.js:重新定义AI驱动的跨平台UI自动化范式

Midscene.js&#xff1a;重新定义AI驱动的跨平台UI自动化范式 【免费下载链接】midscene AI-powered, vision-driven UI automation for every platform. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 在数字化转型浪潮中&#xff0c;UI自动化测试与交互…

作者头像 李华
网站建设 2026/5/14 17:28:23

AI编程助手规则统一管理:基于Git与符号链接的配置同步方案

1. 项目概述&#xff1a;告别混乱的AI规则管理 如果你和我一样&#xff0c;同时在使用 Cursor、GitHub Copilot、Claude Code 这些AI编程助手&#xff0c;那你一定经历过这种痛苦&#xff1a;每个项目里都散落着各种 .mdc 、 .md 规则文件&#xff0c;想更新一下团队的代码…

作者头像 李华
网站建设 2026/5/14 17:28:21

如何用BetterNCM安装器3分钟解锁网易云音乐隐藏功能 [特殊字符]

如何用BetterNCM安装器3分钟解锁网易云音乐隐藏功能 &#x1f3b5; 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 你是否觉得网易云音乐的功能还不够用&#xff1f;想让你的音乐播放器…

作者头像 李华
网站建设 2026/5/14 17:27:12

速腾聚创M1半固态激光雷达 开箱即用指南:从硬件连接到点云可视化

1. 认识速腾聚创M1激光雷达 第一次拿到速腾聚创M1半固态激光雷达时&#xff0c;很多人可能会被这个黑色方盒子的专业外观唬住。其实拆开包装后你会发现&#xff0c;整套设备非常友好。我去年第一次接触M1时也有过同样的顾虑&#xff0c;但实际使用后发现它的设计真的很人性化。…

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

Windows系统深度清理:OneDrive自动化卸载工具实战指南

Windows系统深度清理&#xff1a;OneDrive自动化卸载工具实战指南 【免费下载链接】OneDrive-Uninstaller Batch script to completely uninstall OneDrive in Windows 10 项目地址: https://gitcode.com/gh_mirrors/on/OneDrive-Uninstaller 在Windows 10系统中&#x…

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

独立开发者如何利用 Taotoken 同时为多个客户端项目提供 AI 能力

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 独立开发者如何利用 Taotoken 同时为多个客户端项目提供 AI 能力 作为独立开发者&#xff0c;你很可能同时维护着多个小型客户项目…

作者头像 李华