My App

策略模式

Strategy — 把算法封装成可互换的策略对象,消灭 if-else

一句话理解

定义一系列算法,把每个算法封装成独立的类,让它们可以互相替换。告别大段 if-else。

解决什么问题

// 反面教材:大量 if-else,每加一种方式就要改这个方法
public double calculate(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 (...) // 越来越长...
}
  • 违反开闭原则:新增策略必须修改已有代码
  • 代码臃肿,难以维护
  • 无法独立测试每种策略

怎么写

// 策略接口
public interface PriceStrategy {
    double calculate(double price);
}

// 具体策略
public class NormalStrategy implements PriceStrategy {
    public double calculate(double price) { return price; }
}

public class VipStrategy implements PriceStrategy {
    public double calculate(double price) { return price * 0.8; }
}

public class SvipStrategy implements PriceStrategy {
    public double calculate(double price) { return price * 0.6; }
}

// 上下文:持有一个策略对象
public class PriceCalculator {
    private PriceStrategy strategy;

    public void setStrategy(PriceStrategy strategy) {
        this.strategy = strategy;
    }

    public double calculate(double price) {
        return strategy.calculate(price);
    }
}
PriceCalculator calculator = new PriceCalculator();

calculator.setStrategy(new VipStrategy());
System.out.println(calculator.calculate(100));  // 80.0

calculator.setStrategy(new SvipStrategy());
System.out.println(calculator.calculate(100));  // 60.0

新增折扣策略只需要新加一个类,不用改任何已有代码

前端中的策略

// 表单校验策略
const validators = {
  required: (value: string) => value.length > 0 || '不能为空',
  email: (value: string) => /^[^\s@]+@[^\s@]+$/.test(value) || '邮箱格式错误',
  minLength: (min: number) => (value: string) =>
    value.length >= min || `至少 ${min} 个字符`,
}

// 使用:组合不同的校验策略
function validate(value: string, rules: Function[]) {
  for (const rule of rules) {
    const result = rule(value)
    if (result !== true) return result
  }
  return true
}

validate('', [validators.required])  // '不能为空'

使用场景

  • 支付方式选择(支付宝/微信/银联)
  • 排序算法选择
  • 表单校验规则
  • 日志输出策略(控制台/文件/远程)
  • Spring 中通过 @Autowired 注入不同的策略实现

On this page