Java策略模式从入门到实战:小白也能看懂的设计模式指南
🌟 一句话理解策略模式:把"怎么做"抽出来,让程序能灵活换算法,而不改主逻辑。
① 技术栈用途介绍:它到底能解决什么问题?
想象你开了一家「智能收银小铺」,顾客付款时可选:微信支付、支付宝、现金、会员积分......每种方式的校验规则、扣款流程、成功回调都不一样 。如果用 if-else 硬编码写死在结算方法里:
java
if (payType.equals("wechat")) { /* 微信逻辑 */ }
else if (payType.equals("alipay")) { /* 支付宝逻辑 */ }
// ......10种支付方式?加一个就改一次主方法!
❌ 问题来了:
- 代码臃肿、难以维护;
- 新增支付方式要动核心业务(违反"开闭原则");
- 单元测试困难,逻辑耦合严重。
✅ 策略模式登场:
就像给收银台装上「可插拔的支付卡槽」------微信卡、支付宝卡、现金卡......各自封装好自己的动作,收银员(主业务)只管"插哪张卡、按确认键",不用关心卡内部怎么工作。
📌 典型场景:
- 多种算法切换(排序、压缩、加密);
- 多渠道通知(短信/邮件/钉钉);
- 不同风控策略(新用户宽松、老用户严格);
- 电商促销计算(满减、折扣、赠品)。
② 环境准备与安装配置:5分钟搭好实验环境
无需额外安装!策略模式是纯Java语言级设计思想,JDK 8+ 即可运行(推荐 JDK 17)。你只需要:
✅ 开发工具 :IntelliJ IDEA(社区版免费)或 VS Code + Java Extension Pack ✅ 项目构建:Maven(IDE通常自带)
🔧 创建 Maven 工程(命令行速建):
bash
mvn archetype:generate -DgroupId=com.example.strategy \
-DartifactId=strategy-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
💡 避坑提醒:
- ❌ 不要试图找"策略模式依赖库"------它不是框架,不需要
pom.xml加依赖! - ✅ 关键是理解接口 + 多实现类 + 上下文委托 的三件套结构;
- ⚠️ 若报错
Cannot resolve symbol 'xxx',检查是否漏写public interface/implements/ 包声明。
③ 入门实践:30秒跑通第一个策略Demo
我们以「订单优惠计算」为例,实现:
- 普通订单 → 无优惠
- VIP订单 → 9折
- 黑金订单 → 满200减50
Step 1:定义策略接口
java
// src/main/java/com/example/strategy/PromotionStrategy.java
public interface PromotionStrategy {
double calculateDiscount(double originalPrice);
}
Step 2:编写具体策略实现类
java
// 普通策略
public class NoDiscountStrategy implements PromotionStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return 0.0;
}
}
// VIP策略(9折 → 减10%)
public class VipDiscountStrategy implements PromotionStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return originalPrice * 0.1;
}
}
// 黑金策略(满200减50)
public class BlackGoldStrategy implements PromotionStrategy {
@Override
public double calculateDiscount(double originalPrice) {
return originalPrice >= 200 ? 50.0 : 0.0;
}
}
Step 3:创建上下文(收银员)
java
// src/main/java/com/example/strategy/OrderContext.java
public class OrderContext {
private PromotionStrategy strategy;
public void setStrategy(PromotionStrategy strategy) {
this.strategy = strategy;
}
public double applyDiscount(double price) {
return price - strategy.calculateDiscount(price);
}
}
Step 4:编写测试入口(运行它!)
java
// src/test/java/com/example/strategy/StrategyDemoTest.java
public class StrategyDemoTest {
public static void main(String[] args) {
OrderContext context = new OrderContext();
// 场景1:普通用户下单 ¥100
context.setStrategy(new NoDiscountStrategy());
System.out.println("普通用户实付:" + context.applyDiscount(100)); // 100.0
// 场景2:VIP用户下单 ¥100
context.setStrategy(new VipDiscountStrategy());
System.out.println("VIP用户实付:" + context.applyDiscount(100)); // 90.0
// 场景3:黑金用户下单 ¥250
context.setStrategy(new BlackGoldStrategy());
System.out.println("黑金用户实付:" + context.applyDiscount(250)); // 200.0
}
}
✅ 运行输出:
普通用户实付:100.0
VIP用户实付:90.0
黑金用户实付:200.0
🎉 成功!你已亲手实现了策略模式 ------ 零框架、纯Java、一目了然。
④ 进阶与原理:不止于"能用",更要懂"为什么这么设计"
🔍 核心机制图解
[客户端] → 设置策略 → [OrderContext(上下文)]
↓ 委托调用
[PromotionStrategy(接口)] ← 实现关系 ← [NoDiscount/Vip/BlackGold...]
- 上下文不依赖具体实现:只持有接口,随时可切换;
- 新增策略零侵入 :加个
StudentDiscountStrategy类,不改任何已有代码; - 天然支持依赖注入 :Spring 中可直接
@Autowired注入不同策略 Bean。
🚀 高级技巧(实战加分项)
✅ 策略工厂 + 枚举驱动(告别硬编码 new)
java
public enum PayType {
WECHAT(new WechatStrategy()),
ALIPAY(new AlipayStrategy()),
CASH(new CashStrategy());
private final PromotionStrategy strategy;
PayType(PromotionStrategy strategy) { this.strategy = strategy; }
public PromotionStrategy getStrategy() { return strategy; }
}
// 使用:context.setStrategy(PayType.WECHAT.getStrategy());
✅ Spring整合(自动注册 & 条件化策略)
java
@Component("vipStrategy")
@ConditionalOnProperty(name = "user.level", havingValue = "vip")
public class VipDiscountStrategy implements PromotionStrategy { ... }
⚖️ 性能注意点
- 策略对象建议单例复用(避免频繁 new);
- 高并发下可用
ConcurrentHashMap<String, Strategy>缓存策略实例。
⑤ 总结与评估:什么时候该用?什么时候绕道?
| 维度 | 说明 | |--------------|----------------------------------------------------------------------| | ✅ 优点 | • 开闭原则完美践行(对扩展开放,对修改关闭)
• 解耦清晰,测试友好
• 易于组合、替换、单元化 | | ❌ 局限性 | • 策略过多时类爆炸(如100种支付 → 100个类)→ 可结合工厂/规则引擎优化
• 无法处理策略间强依赖或状态流转 | | 🎯 适用场景 | • 同一行为有多种实现方式
• 业务规则经常变动
• 需要运行时动态选择算法 | | 🆚 vs 状态模式 | 策略关注「算法替换」,状态关注「对象自身状态改变导致行为变化」(如订单:待支付→已发货→已完成) | | 📚 延伸学习 | • 结合 Spring @Qualifier 实现策略注入
• 进阶:Drools 规则引擎(超复杂策略场景)
• 对比学习:模板方法模式(父类定骨架,子类填细节) |
💡 给小白的学习建议:
- 先照着本文 Demo 敲3遍,确保完全理解三要素(接口、实现类、上下文);
- 尝试把「登录验证方式」(账号密码 / 手机验证码 / 第三方OAuth)改成策略模式;
- 阅读 JDK 源码中的
Comparator接口------它就是策略模式的经典应用!
✨ 结语:设计模式不是炫技,而是为代码"延长保质期"。当你不再为加一个新功能而恐惧修改旧代码时,你就真正入门了工程思维。策略模式,是你走向优雅编程的第一步轻装启程。
💬 文末互动:你在项目中用过策略模式吗?遇到过哪些坑?欢迎评论区交流~