一、什么是策略模式?
策略模式(Strategy Pattern) 是一种行为型设计模式,它定义了一系列算法,把它们一个个封装起来,并且使它们可以互换。
策略模式让算法独立于使用它的客户端而变化,也就是“行为的选择权”交给了客户端。
二、为什么要使用策略模式?
✅ 场景痛点:行为选择分支难以维护
面对复杂的行为选择逻辑,我们经常写出如下代码:
if (user.isVip()) {
discount = price * 0.8;
} else if (user.isMember()) {
discount = price * 0.9;
} else {
discount = price;
}
这种代码存在如下问题:
-
条件判断耦合在一起:每次新增一种策略,需修改原有方法
-
违反开闭原则:代码不易扩展
-
测试难、复用性低:行为无法独立测试和复用
✅ 策略模式正是为了解决这类问题而设计:将每种策略抽离成独立类,使其可以互换、动态替换、灵活扩展。
✅ 类比说明:出行策略的选择
不同出行需求下,人们可能会选择:
-
🚗 自驾:适合短途出行
-
🚇 地铁:高峰时通勤利器
-
🚖 打车:便捷但昂贵
这些“出行方式”就是可互换的“策略”,我们可以将它们封装为类,再根据实际情况动态选择最合适的一种。
三、策略模式结构
角色 | 职责说明 |
---|---|
Context | 上下文类,使用策略类并持有其引用 |
Strategy | 抽象策略接口,定义统一的方法 |
ConcreteStrategy | 具体策略类,实现特定的算法 |
四、Java 实现:电商平台折扣策略系统
✅ 1. 抽象策略接口
public interface DiscountStrategy {
double applyDiscount(double price);
}
✅ 2. 具体策略类
原价策略
public class NoDiscountStrategy implements DiscountStrategy {
public double applyDiscount(double price) {
return price;
}
}
会员 9 折策略
public class MemberDiscountStrategy implements DiscountStrategy {
public double applyDiscount(double price) {
return price * 0.9;
}
}
VIP 8 折策略
public class VipDiscountStrategy implements DiscountStrategy {
public double applyDiscount(double price) {
return price * 0.8;
}
}
✅ 3. 上下文类
public class PriceCalculator {
private DiscountStrategy strategy;
public PriceCalculator(DiscountStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calculate(double price) {
return strategy.applyDiscount(price);
}
}
✅ 4. 使用示例
public class Main {
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator(new NoDiscountStrategy());
System.out.println("原价:" + calculator.calculate(100));
calculator.setStrategy(new MemberDiscountStrategy());
System.out.println("会员价:" + calculator.calculate(100));
calculator.setStrategy(new VipDiscountStrategy());
System.out.println("VIP价:" + calculator.calculate(100));
}
}
五、适用场景总结
应用场景 | 描述 |
---|---|
存在多个可互换的行为算法 | 如不同打折、排序、验证算法 |
策略之间行为独立且可替换 | 可以灵活切换策略的场合 |
客户端需在运行时动态选择行为策略 | 用户配置、A/B 测试等 |
六、策略模式的优点
优点 | 说明 |
---|---|
行为独立、职责单一 | 每种策略各自封装 |
满足开闭原则 | 添加新策略不需修改上下文 |
策略可动态切换 | 支持运行时更改策略 |
易于扩展和单元测试 | 策略类独立可复用 |
七、缺点及典型问题场景
缺点 | 问题描述 |
---|---|
策略类数量激增 | 策略越多,类越多 |
客户端需了解所有策略 | 策略选择权交给客户端,增加负担 |
可能出现策略选择逻辑外泄 | 上下文以外决定策略时逻辑分散 |
❌ 场景 1:支付系统策略类激增
在一个国际支付平台中,每个国家 / 支付方式(支付宝、PayPal、微信、信用卡)都有独立计算手续费的策略。
随着业务扩展,策略类数量过多,难以管理。
✅ 解决方案:
-
将策略类归类到包中(按支付渠道划分)
-
使用注册中心 + 简单工厂动态配置策略
❌ 场景 2:客户端选择策略逻辑外泄
客户端需通过如下代码手动判断策略:
if (user.isVip()) {
strategy = new VipDiscountStrategy();
}
✅ 解决方案:
-
引入策略工厂封装选择逻辑
-
或引入配置驱动策略选择(策略由外部配置注入)
八、扩展方向
扩展点 | 描述 |
---|---|
策略注册中心 | 将策略注册到 Map 中,按 key 获取策略 |
与工厂模式结合使用 | 使用工厂动态创建策略实例 |
与配置文件集成 | 根据配置动态指定策略类名并实例化 |
与注解配合使用 | 结合 Spring 注解自动注入策略 |
九、总结
策略模式 是行为切换场景的优雅解法,适用于需要灵活扩展和切换算法的业务逻辑。
📌 适用前提:
-
多种行为算法可互换
-
算法实现独立封装
-
客户端需根据情况选择行为
📌 使用建议:
-
控制策略类数量,避免类爆炸
-
使用策略工厂简化客户端策略选择
-
尽量避免策略选择逻辑外泄
下一篇将带你深入讲解「模版方法模式」的核心思想与进阶用法 👨🏫