告别通勤选择困难症------策略模式
- [一、传统实现的痛点:if-else 的泥潭](#一、传统实现的痛点:if-else 的泥潭)
- 二、策略模式的解法:模块化拆分
- 三、优势对比:策略模式的价值
- 四、应用场景与边界
- 五、设计启示

引子:一个程序员的通勤顿悟时刻
周一清晨,程序员小张盯着手机里的三条提醒发愁:
① 天气App:今日有暴雨⛈️(降水概率90%)
② 导航App:常走路线拥堵1.5公里🚗
③ 健康手环:建议完成30分钟有氧运动🏃
他的大脑开始条件反射式地处理这些输入参数:
java
// 传统if-else思维模式
if (天气 == 暴雨) {
呼叫网约车();
} else if (拥堵距离 > 1公里) {
启动地铁方案();
} else if (需要运动) {
选择共享单车();
} else {
默认自驾方案();
}
突然意识到:每新增一个决策因素(如油价上涨、地铁限流),就要在代码里插入新的else if,就像在已经打结的耳机线上再绕一圈。这促使他思考------是否有更优雅的解决方案?
一、传统实现的痛点:if-else 的泥潭
假设我们需要实现通勤方案选择功能,传统写法通常是这样的:
java
public class CommuteService {
public void chooseTransport(String type, int distance) {
if ("bike".equals(type)) {
System.out.println("骑行方案:");
int time = (int)(distance / 12.0 * 60);
System.out.println("预计耗时:" + time + "分钟");
System.out.println("执行操作:扫码开锁 → 规划骑行路线");
} else if ("subway".equals(type)) {
System.out.println("地铁方案:");
int time = (distance / 2) * 4 + 10;
System.out.println("预计耗时:" + time + "分钟");
System.out.println("执行操作:选择换乘路线 → 安检进站");
} else if ("car".equals(type)) {
System.out.println("自驾方案:");
int time = (int)(distance / 30.0 * 60) + 15;
System.out.println("预计耗时:" + time + "分钟");
System.out.println("执行操作:导航避开限行 → 寻找停车位");
}
// 每新增一种方式就要添加else-if
}
}
传统代码的三大痛点:
- 代码臃肿:当交通工具增加到10种时,方法长度超过100行
- 修改风险:新增或修改某种交通方式时可能影响其他逻辑
- 难以复用:耗时计算与执行逻辑耦合在一起
二、策略模式的解法:模块化拆分
策略模式三要素:
- 策略接口(Strategy Interface):定义算法族的统一规范。声明所有具体策略必须实现的方法
- 具体策略实现(Concrete Strategies):封装具体算法实现。每个类独立实现接口方法,包含特定业务逻辑
- 上下文环境(Context):策略调度与执行协调。持有策略对象的引用,将客户端请求委派给具体策略
java
// 策略接口(规范)
interface TransportStrategy {
int calculateTime(int distance);
void execute();
}
// 具体策略实现
class BikeStrategy implements TransportStrategy {
public int calculateTime(int distance) {
return (int)(distance / 12.0 * 60);
}
public void execute() {
System.out.println("扫码开锁 → 规划骑行路线");
}
}
class SubwayStrategy implements TransportStrategy {
public int calculateTime(int distance) {
return (distance / 2) * 4 + 10;
}
public void execute() {
System.out.println("选择换乘路线 → 安检进站");
}
}
// 上下文环境
class CommuteContext {
private TransportStrategy strategy;
public void setStrategy(TransportStrategy strategy) {
this.strategy = strategy;
}
public void startCommute(int distance) {
System.out.println("预计耗时:" + strategy.calculateTime(distance) + "分钟");
strategy.execute();
}
}
客户端调用:
java
public class Client {
public static void main(String[] args) {
CommuteContext context = new CommuteContext();
// 动态切换策略
context.setStrategy(new BikeStrategy());
context.startCommute(10); // 骑行10公里
context.setStrategy(new SubwayStrategy());
context.startCommute(15); // 地铁15公里
}
}
三、优势对比:策略模式的价值
传统if-else实现 | 策略模式实现 | |
---|---|---|
代码可读性 | 逻辑混杂,难以快速定位 | 模块清晰,每个策略独立文件 |
扩展成本 | 修改原文件,风险高 | 新增类即可,符合开闭原则 |
单元测试 | 需要覆盖所有分支 | 可单独测试每个策略 |
业务复用 | 逻辑无法复用 | 策略可跨场景复用(如配送系统) |
扩展逻辑:
当需要新增「电动车」方案时:
- 传统方式:在原有方法中增加else if ("escooter".equals(type))分支
- 策略模式:创建EscooterStrategy类并实现接口即可
四、应用场景与边界
推荐使用场景:
- 算法族需要自由切换(如加密算法、压缩算法)
- 存在相似但不同的业务规则(如不同地区的税费计算)
- 需要消除多层条件判断(超过3层的if-else)
不适用场景:
- 简单且固定的业务逻辑(如单一算法场景)
- 策略之间强耦合的场景(如必须先执行A策略才能执行B)
五、设计启示
策略模式体现了两个重要的设计原则:
- 开闭原则(OCP) 对扩展开放(新增策略),对修改关闭(不改变上下文)
- 单一职责原则(SRP) 每个策略类只负责一种算法实现
当你在编写充满条件判断的业务代码时,不妨思考:这些逻辑是否可以被抽象为一系列可插拔的策略对象?
这正是策略模式给我们的最佳实践启示。