木木屋免安装绿色中文版
567M · 2025-10-23
各位程序猿/程序媛们,有没有遇到过这样的场景:你的代码里充斥着大量的if-else语句,每次新增一个功能就要在原有的条件判断上再添一笔?就像是你家的遥控器,按钮越来越多,最后连你自己都记不住哪个是干嘛的?
别担心,今天我要介绍的策略模式就是来解决这个问题的https://images.alixixi.com/uploads/20250928/img_68d8c4255057730.png它就像是给你的代码装上一个智能遥控器,每个功能都有独立的按钮,清晰又方便https://images.alixixi.com/uploads/20250928/img_68d8c4255057730.png
在深入策略模式之前,我们先快速了解一下行为设计模式这个大家族。它们主要关注的是对象之间的通信和职责分配,就像是教代码如何优雅地"社交":
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。它让算法的变化独立于使用算法的客户。
简单说就是:把会变化的部分提取出来,封装成独立的策略类。
想象一下,如果你是一个电商平台的开发者,需要实现不同的折扣策略:
没有策略模式的"灾难现场":
public BigDecimal calculateDiscount(String userType, BigDecimal price) {
if ("VIP".equals(userType)) {
return price.multiply(new BigDecimal("0.8"));
} else if ("SVIP".equals(userType)) {
return price.multiply(new BigDecimal("0.7"));
} else if ("NEW_USER".equals(userType)) {
return price.multiply(new BigDecimal("0.9"));
} else if ("EMPLOYEE".equals(userType)) {
return price.multiply(new BigDecimal("0.6"));
}
// 每次新增用户类型都要修改这里https://images.alixixi.com/uploads/20250928/img_68d8c4255057730.png
return price;
}
这种代码的痛点:
策略模式的核心思想:识别变化,封装变化。
就像玩乐高,你把不同的功能模块化,需要什么就拼接什么,而不是把所有的功能都固化在一个大块里。
public interface DiscountStrategy {
/**
* 计算折扣价
* @param price 原价
* @return 折扣价
*/
BigDecimal calculate(BigDecimal price);
/**
* 获取策略类型
* @return 策略类型
*/
String getType();
}
// VIP折扣策略
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price.multiply(new BigDecimal("0.8"));
}
@Override
public String getType() {
return "VIP";
}
}
// 超级VIP折扣策略
public class SuperVipDiscountStrategy implements DiscountStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price.multiply(new BigDecimal("0.7"));
}
@Override
public String getType() {
return "SVIP";
}
}
// 新用户折扣策略
public class NewUserDiscountStrategy implements DiscountStrategy {
@Override
public BigDecimal calculate(BigDecimal price) {
return price.multiply(new BigDecimal("0.9"));
}
@Override
public String getType() {
return "NEW_USER";
}
}
public class DiscountContext {
private DiscountStrategy strategy;
public DiscountContext(DiscountStrategy strategy) {
this.strategy = strategy;
}
// 设置策略(支持动态切换)
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
// 执行计算
public BigDecimal executeStrategy(BigDecimal price) {
if (strategy == null) {
throw new IllegalStateException("请先设置折扣策略");
}
System.out.println("使用" + strategy.getType() + "折扣策略");
return strategy.calculate(price);
}
}
public class StrategyDemo {
public static void main(String[] args) {
// 创建价格
BigDecimal price = new BigDecimal("100");
// 普通用户
DiscountContext context = new DiscountContext(new VipDiscountStrategy());
System.out.println("VIP价格:" + context.executeStrategy(price));
// 动态切换为超级VIP
context.setStrategy(new SuperVipDiscountStrategy());
System.out.println("超级VIP价格:" + context.executeStrategy(price));
// 新用户
context.setStrategy(new NewUserDiscountStrategy());
System.out.println("新用户价格:" + context.executeStrategy(price));
}
}
输出结果:
使用VIP折扣策略
VIP价格:80
使用SVIP折扣策略
超级VIP价格:70
使用NEW_USER折扣策略
新用户价格:90
为了避免每次都要new具体的策略类,我们可以结合工厂模式:
public class DiscountStrategyFactory {
private static final Map<String, DiscountStrategy> strategies = new HashMap<>();
static {
strategies.put("VIP", new VipDiscountStrategy());
strategies.put("SVIP", new SuperVipDiscountStrategy());
strategies.put("NEW_USER", new NewUserDiscountStrategy());
}
public static DiscountStrategy getStrategy(String type) {
DiscountStrategy strategy = strategies.get(type);
if (strategy == null) {
throw new IllegalArgumentException("不支持的折扣类型:" + type);
}
return strategy;
}
// 注册新策略(支持动态扩展)
public static void registerStrategy(String type, DiscountStrategy strategy) {
strategies.put(type, strategy);
}
}
使用方式:
// 从工厂获取策略
DiscountStrategy strategy = DiscountStrategyFactory.getStrategy("VIP");
DiscountContext context = new DiscountContext(strategy);
BigDecimal result = context.executeStrategy(price);
在Spring Boot中,我们可以利用依赖注入让策略模式更加优雅:
@Service
public class DiscountService {
private final Map<String, DiscountStrategy> strategyMap;
// 通过构造函数注入所有策略
public DiscountService(List<DiscountStrategy> strategies) {
this.strategyMap = strategies.stream()
.collect(Collectors.toMap(DiscountStrategy::getType, Function.identity()));
}
public BigDecimal calculateDiscount(String userType, BigDecimal price) {
DiscountStrategy strategy = strategyMap.get(userType);
if (strategy == null) {
throw new IllegalArgumentException("不支持的折扣类型:" + userType);
}
return strategy.calculate(price);
}
}
策略模式就像是给我们的代码装上了"变形金刚"的能力,让算法能够灵活变换。它教会我们一个重要的编程哲学:拥抱变化,而不是抗拒变化。
下次当你看到代码中又出现大段的if-else时,不妨想想:"这里是不是可以用策略模式来优化?"
记住,好的代码不是一次性写出来的,而是不断重构出来的。策略模式就是我们重构工具箱中一件强大的武器https://images.alixixi.com/uploads/20250928/img_68d8c4255057730.png
互动环节:大家在工作中还遇到过哪些适合使用策略模式的场景?欢迎在评论区分享你的实战经验