策略模式
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注入不同的策略实现