Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

策略模式

策略模式用于定义一组可互换的算法或规则,并在运行时选择其中一种执行。

一句话理解:把一堆 if-else 里的算法拆成独立策略。

解决什么问题

支付、折扣、路由、导出、计算规则等业务经常会出现这样的代码:

java
if ("vip".equals(type)) {
    // vip discount
} else if ("new_user".equals(type)) {
    // new user discount
} else if ("festival".equals(type)) {
    // festival discount
}

当规则越来越多时,主流程会变得很难维护。策略模式把每种算法封装成一个类,让主流程只负责选择和调用。

基本结构

text
Context -> Strategy
            ^
            |
    ConcreteStrategy

角色:

  • Strategy:策略接口。
  • ConcreteStrategy:具体策略。
  • Context:上下文,选择并执行策略。

Java 示例

策略接口:

java
interface DiscountStrategy {
    String type();

    int discount(int originAmount);
}

具体策略:

java
class VipDiscountStrategy implements DiscountStrategy {
    public String type() {
        return "vip";
    }

    public int discount(int originAmount) {
        return (int) (originAmount * 0.8);
    }
}

class NewUserDiscountStrategy implements DiscountStrategy {
    public String type() {
        return "new_user";
    }

    public int discount(int originAmount) {
        return originAmount - 1000;
    }
}

策略上下文:

java
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class DiscountService {
    private final Map<String, DiscountStrategy> strategyMap = new HashMap<>();

    DiscountService(List<DiscountStrategy> strategies) {
        for (DiscountStrategy strategy : strategies) {
            strategyMap.put(strategy.type(), strategy);
        }
    }

    public int calculate(String type, int originAmount) {
        DiscountStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("unsupported discount type: " + type);
        }
        return strategy.discount(originAmount);
    }
}

使用:

java
import java.util.Arrays;

DiscountService service = new DiscountService(Arrays.asList(
        new VipDiscountStrategy(),
        new NewUserDiscountStrategy()
));

int amount = service.calculate("vip", 10000);

Spring 中的常见写法

在 Spring 中,可以把所有策略注入进来:

java
@Service
public class DiscountService {
    private final Map<String, DiscountStrategy> strategyMap;

    public DiscountService(List<DiscountStrategy> strategies) {
        this.strategyMap = strategies.stream()
                .collect(Collectors.toMap(DiscountStrategy::type, Function.identity()));
    }
}

新增策略时,只要新增一个实现类并交给 Spring 管理。

使用场景

  • 优惠计算。
  • 支付渠道。
  • 文件导出。
  • 消息发送渠道。
  • 排序算法。
  • 规则路由。
  • 根据类型选择不同处理逻辑。

优点

  • 消除复杂 if-else
  • 每个策略独立维护。
  • 新增策略不影响主流程。
  • 方便单独测试每个策略。

缺点

  • 策略类数量会增加。
  • 调用方或上下文需要知道选择哪种策略。
  • 策略之间如果有大量重复代码,需要再抽公共逻辑。

和工厂模式的关系

策略模式负责“怎么做”,工厂模式负责“创建谁”。

实际项目中经常组合使用:

text
工厂/Map 找到策略
策略执行具体算法

实战注意

策略模式最适合替换同一业务点上的多种算法。如果这些分支逻辑并不属于同一抽象,强行抽成策略会让代码更绕。

以工程实践沉淀知识,以文档复盘成长。