目录

策略模式 (Strategy Pattern)

定义算法族,分别封装起来,让它们可以互相替换

概述

策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。

适用场景

  • 多种方式完成相同任务
  • 需要动态切换算法
  • 避免多重条件判断

基础实现

// 策略接口
public interface PaymentStrategy {
    void pay(BigDecimal amount);
    String getName();
}

// 具体策略:支付宝
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("支付宝支付: ¥" + amount);
    }
    
    @Override
    public String getName() {
        return "支付宝";
    }
}

// 具体策略:微信支付
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("微信支付: ¥" + amount);
    }
    
    @Override
    public String getName() {
        return "微信支付";
    }
}

// 具体策略:银行卡
public class CardPayStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("银行卡支付: ¥" + amount);
    }
    
    @Override
    public String getName() {
        return "银行卡";
    }
}

// 上下文
public class PaymentContext {
    private PaymentStrategy strategy;
    
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void executePayment(BigDecimal amount) {
        strategy.pay(amount);
    }
}

// 使用
PaymentContext context = new PaymentContext();

// 选择支付宝
context.setStrategy(new AlipayStrategy());
context.executePayment(new BigDecimal("100"));

// 切换到微信支付
context.setStrategy(new WechatPayStrategy());
context.executePayment(new BigDecimal("200"));

Spring 集成

// 策略接口
public interface DiscountStrategy {
    BigDecimal calculateDiscount(BigDecimal originalPrice);
    String getType();
}

// 具体策略
@Component
public class NormalDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calculateDiscount(BigDecimal price) {
        return price; // 无折扣
    }
    
    @Override
    public String getType() {
        return "NORMAL";
    }
}

@Component
public class VipDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calculateDiscount(BigDecimal price) {
        return price.multiply(new BigDecimal("0.8")); // VIP 8折
    }
    
    @Override
    public String getType() {
        return "VIP";
    }
}

@Component
public class SuperVipDiscountStrategy implements DiscountStrategy {
    @Override
    public BigDecimal calculateDiscount(BigDecimal price) {
        return price.multiply(new BigDecimal("0.5")); // 超级VIP 5折
    }
    
    @Override
    public String getType() {
        return "SUPER_VIP";
    }
}

// 策略工厂
@Component
public class DiscountStrategyFactory {
    private final Map<String, DiscountStrategy> strategies = new HashMap<>();
    
    public DiscountStrategyFactory(List<DiscountStrategy> strategyList) {
        for (DiscountStrategy strategy : strategyList) {
            strategies.put(strategy.getType(), strategy);
        }
    }
    
    public DiscountStrategy getStrategy(String type) {
        DiscountStrategy strategy = strategies.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException("未知的折扣类型: " + type);
        }
        return strategy;
    }
}

// 使用
@Service
public class OrderService {
    @Autowired
    private DiscountStrategyFactory strategyFactory;
    
    public BigDecimal calculatePrice(String userType, BigDecimal originalPrice) {
        DiscountStrategy strategy = strategyFactory.getStrategy(userType);
        return strategy.calculateDiscount(originalPrice);
    }
}

框架中的应用

Java Comparator

// Comparator 是策略接口
List<String> names = Arrays.asList("Tom", "JERRY", "alice");

// 策略1:自然排序
names.sort(Comparator.naturalOrder());

// 策略2:忽略大小写
names.sort(String.CASE_INSENSITIVE_ORDER);

// 策略3:按长度排序
names.sort(Comparator.comparingInt(String::length));

// 策略4:自定义排序
names.sort((a, b) -> a.length() - b.length());

Spring Validation

// Spring 的 Validator 是策略模式
public interface Validator {
    boolean supports(Class<?> clazz);
    void validate(Object target, Errors errors);
}

// 不同的验证器实现不同的验证策略
@Component
public class UserValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return User.class.equals(clazz);
    }
    
    @Override
    public void validate(Object target, Errors errors) {
        // 验证逻辑
    }
}

ThreadPoolExecutor 拒绝策略

// 拒绝策略枚举
new ThreadPoolExecutor(
    5, 10, 60L, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),
    // 选择拒绝策略
    new ThreadPoolExecutor.CallerRunsPolicy()  // 调用者执行
    // new ThreadPoolExecutor.AbortPolicy()    // 抛出异常
    // new ThreadPoolExecutor.DiscardPolicy()  // 静默丢弃
    // new ThreadPoolExecutor.DiscardOldestPolicy() // 丢弃最老任务
);

实际应用:排序策略

// 排序策略接口
public interface SortStrategy {
    <T extends Comparable<T>> void sort(List<T> list);
    String getName();
}

// 快速排序
@Component
public class QuickSortStrategy implements SortStrategy {
    @Override
    public <T extends Comparable<T>> void sort(List<T> list) {
        quickSort(list, 0, list.size() - 1);
    }
    
    private <T extends Comparable<T>> void quickSort(List<T> list, int low, int high) {
        if (low < high) {
            int pi = partition(list, low, high);
            quickSort(list, low, pi - 1);
            quickSort(list, pi + 1, high);
        }
    }
    
    private <T extends Comparable<T>> int partition(List<T> list, int low, int high) {
        T pivot = list.get(high);
        int i = low - 1;
        for (int j = low; j < high; j++) {
            if (list.get(j).compareTo(pivot) <= 0) {
                i++;
                Collections.swap(list, i, j);
            }
        }
        Collections.swap(list, i + 1, high);
        return i + 1;
    }
    
    @Override
    public String getName() {
        return "QUICK_SORT";
    }
}

// 归并排序
@Component
public class MergeSortStrategy implements SortStrategy {
    @Override
    public <T extends Comparable<T>> void sort(List<T> list) {
        if (list.size() > 1) {
            mergeSort(list, 0, list.size() - 1);
        }
    }
    
    // 实现归并排序...
    
    @Override
    public String getName() {
        return "MERGE_SORT";
    }
}

// 排序服务
@Service
public class SortService {
    @Autowired
    private Map<String, SortStrategy> strategies;
    
    public <T extends Comparable<T>> List<T> sort(List<T> list, String algorithm) {
        SortStrategy strategy = strategies.get(algorithm);
        if (strategy == null) {
            throw new IllegalArgumentException("未知的排序算法");
        }
        
        List<T> copy = new ArrayList<>(list);
        strategy.sort(copy);
        return copy;
    }
}

与状态模式对比

策略模式状态模式
客户端选择算法状态自动转换
算法平等独立状态有先后顺序
替换整个算法根据条件改变行为

优缺点

优点缺点
消除条件判断类数量增加
易于扩展客户端需了解策略
复用性好

总结

策略模式是消除 if-else/switch 的有效手段。在 Spring 中结合依赖注入可以实现优雅的策略管理。注意策略数量过多时考虑使用工厂模式管理。