策略模式和工厂模式是"黄金搭档",也是消除 if/else 分支的两把利器。这篇把策略模式单独捋一遍:它解决什么、怎么落地、和工厂模式怎么配合、以及它和观察者模式容易被混淆的点。
一、解决什么问题
策略模式解决的是 一坨 if/else 或 switch 的分支坏味道。
java
// 折扣计算:每加一种折扣,就加一个 if 分支,函数越来越长
public double calc(String type, double price) {
if ("normal".equals(type)) {
return price;
} else if ("vip".equals(type)) {
return price * 0.8;
} else if ("svip".equals(type)) {
return price * 0.6;
} else if ("new".equals(type)) {
return price * 0.9;
}
return price;
}问题是:每加一种策略就要改这个函数(违反开闭原则),而且所有策略的逻辑堆在一起,函数越写越长、越来越难维护。
策略模式把每种算法封装成一个独立的类,让它们可以互相替换。
二、策略模式怎么落地
三个角色:
- 策略接口(Strategy):定义算法规范
- 具体策略(ConcreteStrategy):每种算法一个类
- 上下文(Context):持有一个策略引用,负责调用
java
// ① 策略接口
public interface DiscountStrategy {
double discount(double price);
}
// ② 具体策略:每种折扣一个类
public class NormalDiscount implements DiscountStrategy {
public double discount(double price) { return price; }
}
public class VipDiscount implements DiscountStrategy {
public double discount(double price) { return price * 0.8; }
}
public class SvipDiscount implements DiscountStrategy {
public double discount(double price) { return price * 0.6; }
}
// ③ 上下文:持有策略,负责调用
public class PriceContext {
private DiscountStrategy strategy;
public PriceContext(DiscountStrategy strategy) { this.strategy = strategy; }
public double calc(double price) { return strategy.discount(price); }
}
// 使用
PriceContext ctx = new PriceContext(new VipDiscount());
double result = ctx.calc(100); // 80.0现在加一种折扣 = 新增一个策略类,不改任何已有代码,if/else 消失了。
三、和工厂模式配合(黄金搭档)
策略模式本身不解决"用哪个策略"的问题——还是得有人选策略。这时工厂模式就来了:
java
// 工厂负责"创建哪个策略"
public class StrategyFactory {
public static DiscountStrategy create(String type) {
switch (type) {
case "vip": return new VipDiscount();
case "svip": return new SvipDiscount();
default: return new NormalDiscount();
}
}
}
// 组合:工厂选策略 + 策略执行算法
PriceContext ctx = new PriceContext(StrategyFactory.create("vip"));
ctx.calc(100);分工很清晰:
| 模式 | 职责 |
|---|---|
| 工厂模式 | 创建哪个策略对象(解决"选谁") |
| 策略模式 | 执行哪种算法(解决"怎么做") |
工厂模式更详细的讲解见《工厂模式》。
四、策略模式 vs 观察者模式(易混)
两者经常被一起提,但解决的是完全不同的问题:
| 维度 | 策略模式 | 观察者模式 |
|---|---|---|
| 目的 | 算法的可替换 | 状态的变化通知 |
| 关系 | 上下文主动持有一个策略 | 主题维护一群观察者 |
| 触发 | 调用时选择算法 | 事件发生时广播通知 |
| 典型场景 | 折扣、排序、支付渠道 | 事件监听、发布订阅、消息推送 |
一句话区分:策略是"我来选算法",观察者是"你变了通知我"。
小结
- 策略模式消除
if/else分支,把每种算法封装成独立类,符合开闭原则 - 三要素:策略接口 + 具体策略 + 上下文
- 和工厂模式是黄金搭档:工厂"创建"策略,策略"执行"算法
- 与观察者模式区分:策略=算法可替换,观察者=状态变化通知
下一步可以看《观察者模式》——它讲"状态变了怎么通知一堆监听者",是事件驱动、消息队列的底层思想(文章整理中,也会讲清它和发布订阅模式的区别)。
