跳到主要内容

策略模式

问题

什么是策略模式?Java / Spring 项目中如何使用策略模式消除 if-else?

答案

核心思想

将一组算法封装成独立的策略类,使它们可以互相替换。客户端不关心具体使用哪个算法,运行时动态选择。

基础实现

策略模式消除 if-else
// 策略接口
public interface PricingStrategy {
BigDecimal calculate(BigDecimal price);
}

// 普通会员:不打折
public class NormalPricing implements PricingStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price;
}
}

// VIP 会员:打 8 折
public class VipPricing implements PricingStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price.multiply(new BigDecimal("0.8"));
}
}

// SVIP:打 6 折
public class SvipPricing implements PricingStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price.multiply(new BigDecimal("0.6"));
}
}

Spring 中自动收集策略

利用 Spring IoC 自动注入所有策略实现,避免手动维护 Map。

Spring 自动收集 + 策略工厂
// 在每个策略上标注类型
public interface PricingStrategy {
String getType(); // 返回策略标识
BigDecimal calculate(BigDecimal price);
}

@Component
public class NormalPricing implements PricingStrategy {
@Override
public String getType() { return "NORMAL"; }

@Override
public BigDecimal calculate(BigDecimal price) { return price; }
}

// 策略工厂:Spring 自动注入所有实现
@Component
public class PricingStrategyFactory {
private final Map<String, PricingStrategy> strategyMap;

// Spring 会自动注入所有 PricingStrategy 实现
public PricingStrategyFactory(List<PricingStrategy> strategies) {
this.strategyMap = strategies.stream()
.collect(Collectors.toMap(PricingStrategy::getType, Function.identity()));
}

public PricingStrategy get(String type) {
PricingStrategy strategy = strategyMap.get(type);
if (strategy == null) {
throw new IllegalArgumentException("不支持的策略类型: " + type);
}
return strategy;
}
}

// 使用:新增策略只需加一个类,无需修改任何已有代码
@Service
public class OrderService {
@Autowired
private PricingStrategyFactory factory;

public BigDecimal calculatePrice(String memberType, BigDecimal price) {
return factory.get(memberType).calculate(price);
}
}
为什么比 if-else 好?
  1. 开闭原则:新增策略只加一个类,不改已有代码
  2. 单一职责:每个策略类只管一件事
  3. 易于测试:每个策略可以独立单测

常见面试问题

Q1: 策略模式和工厂模式的区别?

答案

维度工厂模式策略模式
关注点创建对象选择算法
结果返回不同类型的产品执行不同的行为
典型场景根据类型创建对象根据条件执行不同算法

实际项目中经常组合使用:工厂负责创建策略对象,策略负责执行具体逻辑。

Q2: 策略模式在 Java 中有哪些典型应用?

答案

  1. Comparator:不同排序策略(Collections.sort(list, comparator)
  2. ThreadPoolExecutor 拒绝策略:4 种 RejectedExecutionHandler
  3. Spring Resource:ClassPathResource、FileSystemResource、UrlResource
  4. 支付、物流、定价等业务场景

Q3: 如何用枚举实现简单的策略模式?

答案

public enum DiscountStrategy {
NORMAL {
@Override
public BigDecimal apply(BigDecimal price) { return price; }
},
VIP {
@Override
public BigDecimal apply(BigDecimal price) {
return price.multiply(new BigDecimal("0.8"));
}
};

public abstract BigDecimal apply(BigDecimal price);
}

// 使用
BigDecimal finalPrice = DiscountStrategy.valueOf("VIP").apply(price);

适合策略数量固定且逻辑简单的场景。

相关链接