👉这是一个或许对你有用的社群
🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:
《项目实战(视频)》:从书中学,往事中“练”
《互联网高频面试题》:面朝简历学习,春暖花开
《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题
《精进 Java 学习指南》:系统学习,互联网主流技术栈
《必读 Java 源码专栏》:知其然,知其所以然
👉这是一个或许对你有用的开源项目
国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构
RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:
多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro
微服务:https://gitee.com/zhijiantianya/yudao-cloud
视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本
来源:
这道题面试官真正在筛什么
30 分答案:背得出策略模式 4 个核心优势
60 分答案:用真实业务场景演示 if-else 怎么烂的
90 分答案:知道何时不该上策略模式
直接掉分的几种答法
高频追问怎么接
我的判断
这道题面试官真正在筛什么
「3 个 if-else 也要用策略模式吗?」——这道京东面试题表面问「该不该上策略模式」——其实在筛 3 个能力:
能不能讲清策略模式真正解决什么问题——不是「让代码看起来像 OOP」,是开闭原则 + 单一职责 + 可测试 + 可复用——光说"代码更整洁"是面试官最讨厌的空话;
会不会用真实业务场景讲清"if-else 怎么变烂的"——光画几个抽象
Type1 / Type2 / Type3是背书,用促销 / 支付 / 风控这种真实场景演示才是踩过坑的;有没有「不该上策略模式」的工程判断力——这是最关键的加分项——面试官最怕招到无脑套设计模式的人——3 个 if-else 也要上、把项目搞成 100 个微小的策略类——这种人接手老项目就是灾难。
按这三档,下面给30 / 60 / 90 分答案。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
30 分答案:背得出策略模式 4 个核心优势
如果只能用 30 秒回答,先列策略模式 vs if-else 的 4 个核心差异:
优势 | if-else | 策略模式 |
|---|---|---|
| 新增分支 | 改原方法、违反开闭原则 | 新加一个策略类、不动原代码 |
| 单一职责 | 所有逻辑挤在一个方法里 | 每个策略一个独立类 |
| 可测试性 | 要构造各种条件测一个方法 | 每个策略类独立写单测 |
| 可复用性 | 逻辑绑死在方法里 | 策略类可在任何地方注入 |
一句话兜底:策略模式不是"为了模式而模式"——是用「类的扩展」替代「方法的修改」——本质是开闭原则的体现。
但仅答到这 = 30 分线——背得出概念但没踩过坑、面试官还会追问。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
60 分答案:用真实业务场景演示 if-else 怎么烂的
到 60 分线,必须用一个真实业务场景讲清"if-else 是怎么从 50 行烂成 500 行的"。
场景:电商促销系统(运营每周加新活动类型)
最初版本只有 3 种促销,一个if-else看起来很合理:
public BigDecimal calculatePrice(String promotionType, BigDecimal price) { if ("normal".equals(promotionType)) { return price; // 无优惠 } else if ("discount".equals(promotionType)) { return price.multiply(new BigDecimal("0.8")); // 打八折 } else if ("fullReduction".equals(promotionType)) { return price.compareTo(new BigDecimal("100")) >= 0 ? price.subtract(new BigDecimal("20")) : price; // 满 100 减 20 } throw new IllegalArgumentException("未知促销类型"); }3 个分支没什么问题——这就是 90 分答案那一节会讲的「不该上策略模式」的场景。
但运营开始隔三差五加活动——半年后这个方法变成这样:
public BigDecimal calculatePrice(String promotionType, BigDecimal price) { if ("normal".equals(promotionType)) { ... } elseif ("discount".equals(promotionType)) { ... } elseif ("fullReduction".equals(promotionType)) { ... } elseif ("buyOneGetOne".equals(promotionType)) { ... } elseif ("newUser".equals(promotionType)) { ... } elseif ("vip".equals(promotionType)) { ... } elseif ("groupBuy".equals(promotionType)) { ... } // ... 还有 13 个分支 }真实项目里:促销类型 20+ 种、每个分支不止一行(要查用户等级、查活动库存、计算叠加优惠),一个方法 500+ 行不是梦。
4 个翻车点全来了:
❌ 加「拼团优惠」要在 500 行方法里找位置插一个
else if——祈祷不影响其他逻辑;❌ 改
fullReduction的 bug、手一抖把buyOneGetOne也改了;❌ 想单独测「满减」的计算——要构造一堆参数跑整个方法;
❌ 另一个服务也想用「打折」——只能复制粘贴。
用 Spring 注入解构成策略模式
// 策略接口 publicinterface PromotionStrategy { BigDecimal calculate(BigDecimal price); } // 每个促销一个独立类 @Component("discount") publicclass DiscountStrategy implements PromotionStrategy { @Override public BigDecimal calculate(BigDecimal price) { return price.multiply(new BigDecimal("0.8")); } } @Component("fullReduction") publicclass FullReductionStrategy implements PromotionStrategy { @Override public BigDecimal calculate(BigDecimal price) { return price.compareTo(new BigDecimal("100")) >= 0 ? price.subtract(new BigDecimal("20")) : price; } }业务代码:
@Service publicclass PromotionService { @Autowired private Map<String, PromotionStrategy> strategyMap; // Spring 自动把所有 PromotionStrategy 实现注入这个 Map // key = Bean 名称,value = 策略实例 public BigDecimal calculatePrice(String promotionType, BigDecimal price) { PromotionStrategy strategy = strategyMap.get(promotionType); if (strategy == null) { thrownew IllegalArgumentException("未知促销类型:" + promotionType); } return strategy.calculate(price); } }4 个翻车点全消失:
痛点 | if-else 处理方式 | 策略模式处理方式 |
|---|---|---|
新增「拼团」 | 在 500 行方法里加 | 新加一个GroupBuyStrategy.java、@Component("groupBuy")——一行原代码不动 |
改满减 bug | 可能误伤打折 | 只改FullReductionStrategy、其他文件不受影响 |
测试满减 | 跑整个方法 | new FullReductionStrategy().calculate(...)直接测 |
复用打折 | 复制粘贴 | 注入DiscountStrategy即可 |
讲到这就到 60 分线——能用真实场景演示 + 解出 4 个痛点的对应解。
90 分答案:知道何时不该上策略模式
90 分线的关键——策略模式有缺点——光夸不批评 = 没思考过。
缺点 1:类爆炸
每加一种策略多一个类。20 种促销 = 20 个文件——文件树会变长、新人找代码要多一步。
修法:① 给策略类加业务前缀(PromotionDiscountStrategy而不是DiscountStrategy);②同业务的策略放同一个包里,不要散落在 service 各处。
缺点 2:客户端要知道有哪些策略
问题:调用方要传"discount"这种字符串——typo 一个字母运行时才报错。
修法:用枚举做策略 key替代字符串:
public enum PromotionType { NORMAL("normal"), DISCOUNT("discount"), FULL_REDUCTION("fullReduction"); // ... } // 调用 strategyMap.get(PromotionType.DISCOUNT.getCode()); // 编译期检查,typo 不了缺点 3:跨策略的通用逻辑要抽
10 种促销都要先校验用户等级、再校验活动库存——这部分通用逻辑塞到哪?
修法:
抽法 | 实现 |
|---|---|
| 抽象类 (推荐) | AbstractPromotionStrategy——通用逻辑写在父类、各策略只重写 |
| 责任链 | 用一条链把「校验 → 计算」串起来——校验失败直接退出 |
何时不该上策略模式?
判断标准(一张表):
维度 | 用 if-else | 上策略模式 |
|---|---|---|
| 分支数量 | ≤ 3 个 | ≥ 5 个 |
| 未来扩展性 | 几年都不会变 | 经常加新分支 |
| 每个分支的代码量 | < 5 行 | > 20 行 |
| 是否需要独立测试 | 不需要 | 需要 |
| 是否被多处复用 | 仅一处 | 多处 |
我的判断标准(一句话):「分支少且稳定用 if-else,分支多且常变上策略」——这就是3 个 if-else 不该上策略模式的核心理由。
面试中的反问技巧:面试官问「3 个 if-else 该不该用策略模式」——正面答完后反问一句:「这 3 个分支未来会不会扩展?每个分支的代码量大概多少?需不需要独立测试?」——这一反问就比直接答更有专业感——面试官会给你打高分。
直接掉分的几种答法
❌ "策略模式更好,应该用"→ -50 分。任何「绝对优先」的答案都暴露没思考过——面试官就在等这种反应。
❌ "3 个分支也要上策略模式(讲了 4 个优势)"→ 直接被刷。3 个简单分支的
if-else是最自然的写法——上策略模式 =过度设计的活样本。❌ "if-else 是反模式"→ 大学课本水平。if-else 不是反模式——滥用的 if-else 才是反模式——这一字之差是工程素养的分水岭。
❌ 只讲优点不讲缺点→ 顶多 60 分。会不会讲缺点是 90 分线的核心区分。
❌ "策略模式肯定能消灭所有 if-else"→ -30 分。**
if (strategyMap.get(type) == null)这种 null 检查的if** 改不掉——消灭的是「业务分支」,不是所有 if。
高频追问怎么接
追问 1:策略模式有什么替代方案?
4 种——按推荐度排:
替代方案 | 适用场景 |
|---|---|
Map<String, Function> | 简单计算逻辑——用 lambda 替代策略类——轻量级首选 |
| 枚举(enum) | 分支固定、不会扩展——每个枚举实例实现接口方法——最简洁 |
| 工厂模式 + 多态 | 策略需要复杂初始化(注入 dao / 配置) |
| 责任链模式 | 多个策略按顺序匹配——找到第一个 match 的就用 |
追问 2:项目里在哪用到了?
这题要结合自己项目讲——常见落地点:
支付方式选择:微信 / 支付宝 / 银联 / 余额——每种一个
PaymentStrategy;促销折扣计算:满减 / 折扣 / 拼团 / VIP——上面演示的那个;
消息推送渠道:站内信 / 短信 / 邮件 / Push——每种一个
NotifyStrategy;数据导出格式:Excel / CSV / PDF / JSON——每种一个
ExportStrategy;风控策略:黑名单 / 速率限制 / 设备指纹 / 行为分析——每种一个
RiskStrategy。
追问 3:策略模式 vs 状态模式有啥区别?
结构上几乎一样——但意图不同:
策略模式:让客户端选策略——「我要打八折」 / 「我要满减」——主动决定;
状态模式:对象内部状态变化导致行为变化——订单从「待支付」 → 「已支付」 → 「已发货」——对象自动迁移。
记忆口诀:策略是给的、状态是变的。
追问 4:策略类一直在新增、文件树越来越长怎么办?
3 个办法:
按业务模块分包:
promotion/strategy/、payment/strategy/而不是strategy/大杂烩;配置化策略:把简单计算逻辑(如折扣率)抽到配置文件 / 数据库,用一个通用
ConfigDrivenStrategy替代多个简单类;分层抽象:基类抽公共逻辑、子类只写差异——减少类的总数。
我的判断
这道题答到 30 分容易、答到 60 分要会用真实业务讲、答到 90 分靠工程判断力。
面试时 3 步走法:
先讲 4 个优势→ 过基础线;
用真实场景(促销 / 支付)演示 if-else 怎么变烂的、策略模式怎么解→ 60 分;
最后甩工程判断:「分支少且稳定用
if-else,分支多且常变才上策略模式」——3 个 if-else 我自己也写 if-else→ 直接 90 分线。
说到底:设计模式是工具——不是炫技的资本。你能说出"什么时候不该用 X"——比 100 个能背出 X 用法的候选人都值钱。面试官这道题筛的就是这种判断力——背模式背不到、踩坑才能踩到。
最后一句:如果哪天你看老代码看到 100 个微小的策略类——大概率是过去某位"想表演设计模式"的同事留下的债。好工程师不是用最多模式的人——是知道什么时候不用模式的人。
欢迎加入我的知识星球,全面提升技术能力。
👉 加入方式,“长按”或“扫描”下方二维码噢:
星球的内容包括:项目实战、面试招聘、源码解析、学习路线。
文章有帮助的话,在看,转发吧。 谢谢支持哟 (*^__^*)