你好,我是风一样的树懒,一个工作十多年的后端专家,曾就职京东、阿里等多家互联网头部企业。公众号“吴计可师”,已经更新了近百篇高质量的面试相关文章,喜欢的朋友欢迎关注点赞
策略模式详解
一、定义与核心思想
策略模式(Strategy Pattern) 是一种行为型设计模式,通过定义一系列算法族并使其可相互替换,让算法独立于使用它的客户端而变化。其核心在于封装变化点,将算法的选择与执行解耦,使得系统更灵活、易于扩展。
二、适用场景
- 多种算法变体:如支付方式(支付宝/微信/银联)、排序算法(快速排序/归并排序)。
- 运行时动态切换策略:如游戏角色根据装备切换攻击方式。
- 替代复杂条件分支:消除代码中大量的
if-else或switch-case。 - 算法复用:多个类需要共享相同算法的不同实现。
三、模式结构
| 角色 | 职责 |
|---|---|
| 策略接口(Strategy) | 定义算法族的公共接口(如PaymentStrategy)。 |
| 具体策略(Concrete Strategy) | 实现策略接口的具体算法(如AlipayStrategy、WeChatPayStrategy)。 |
| 上下文(Context) | 持有策略引用,负责调用具体策略(如Order类)。 |
四、实现示例:支付策略选择
// 策略接口
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略:支付宝支付
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("支付宝支付:" + amount + "元");
}
}
// 具体策略:微信支付
public class WeChatPayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("微信支付:" + amount + "元");
}
}
// 上下文:订单类
public class Order {
private PaymentStrategy strategy;
private double total;
public Order(double total) {
this.total = total;
}
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment() {
if (strategy != null) {
strategy.pay(total);
} else {
throw new IllegalStateException("未选择支付方式");
}
}
}
// 客户端使用
Order order = new Order(100.0);
order.setPaymentStrategy(new AlipayStrategy()); // 动态切换策略
order.executePayment(); // 输出:支付宝支付:100.0元
order.setPaymentStrategy(new WeChatPayStrategy());
order.executePayment(); // 输出:微信支付:100.0元
五、核心优势
- 开闭原则:新增策略无需修改上下文代码。
- 消除条件分支:替代冗长的
if-else逻辑,提升可维护性。 - 算法复用:不同上下文可共享同一策略实现。
- 运行时灵活性:动态切换策略,适应多变需求。
六、应用案例
-
Java Comparator:通过传递不同
Comparator实现定制排序规则。List<Integer> nums = Arrays.asList(3,1,4); nums.sort(Comparator.reverseOrder()); // 策略:逆序排序 -
Spring ResourceLoader:根据资源前缀(
classpath:、http:)选择加载策略。 -
电商促销活动:满减、折扣、赠品等促销策略灵活组合。
-
游戏AI行为:NPC根据环境切换移动策略(巡逻/追击/逃跑)。
七、进阶技巧
1. 策略工厂优化
public class PaymentStrategyFactory {
private static Map<String, PaymentStrategy> strategies = new HashMap<>();
static {
strategies.put("alipay", new AlipayStrategy());
strategies.put("wechat", new WeChatPayStrategy());
}
public static PaymentStrategy getStrategy(String type) {
return strategies.getOrDefault(type, () -> {
throw new UnsupportedOperationException("不支持的支付类型");
});
}
}
// 使用
order.setPaymentStrategy(PaymentStrategyFactory.getStrategy("alipay"));
2. Lambda简化策略
Java 8+ 可使用函数式接口替代策略类:
public class Order {
private Consumer<Double> paymentStrategy;
public void setPaymentStrategy(Consumer<Double> strategy) {
this.paymentStrategy = strategy;
}
public void executePayment() {
paymentStrategy.accept(total);
}
}
// 客户端
order.setPaymentStrategy(amount -> System.out.println("信用卡支付:" + amount));
八、注意事项
- 策略类数量:过多策略可能导致类膨胀,可结合其他模式优化。
- 策略无状态:若策略需维护状态,需确保线程安全。
- 客户端感知策略:需权衡是否暴露策略选择逻辑给客户端。
九、与其他模式对比
| 模式 | 核心差异 |
|---|---|
| 状态模式 | 策略模式客户端主动选择策略;状态模式自动切换状态。 |
| 工厂模式 | 工厂模式创建对象;策略模式管理算法实现。 |
| 模板方法模式 | 模板方法在父类定义流程;策略模式完全替换算法。 |
十、总结
策略模式通过抽象算法实现与动态绑定机制,为系统提供了高度灵活性和可维护性。其核心价值在于:
- 解耦算法定义与使用,符合单一职责原则。
- 支持快速扩展新策略,适应业务变化。
- 提升代码可读性,消除复杂条件判断。
在需要灵活切换算法或消除重复条件分支的场景中,策略模式是提升代码质量的利器。
今天文章就分享到这儿,喜欢的朋友可以关注我的公众号,回复“进群”,可进免费技术交流群。博主不定时回复大家的问题。 公众号:吴计可师