策略模式是行为型设计模式中最常用且最灵活的模式之一,它通过定义算法族、封装每个算法,并使它们可以互相替换,让算法的变化独立于使用算法的客户端。
┌─────────────────┐ ┌──────────────────┐
│ Context │ │ Strategy │
├─────────────────┤ ├──────────────────┤
│ -strategy:Strategy│<>────│ +execute():void │
├─────────────────┤ └──────────────────┘
│ +setStrategy() │ ▲
│ +executeStrategy()│ │
└─────────────────┘ ┌─────────┴──────────┐
│ │
┌──────────────────┐ ┌──────────────────┐
│ ConcreteStrategyA │ │ ConcreteStrategyB │
├──────────────────┤ ├──────────────────┤
│ +execute() │ │ +execute() │
└──────────────────┘ └──────────────────┘
// 策略接口
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略类
public class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String cvv;
public CreditCardPayment(String cardNumber, String cvv) {
this.cardNumber = cardNumber;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using Credit Card");
}
}
public class PayPalPayment implements PaymentStrategy {
private String email;
public PayPalPayment(String email) {
this.email = email;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using PayPal");
}
}
// 上下文类
public class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void checkout(double amount) {
paymentStrategy.pay(amount);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 使用信用卡支付
cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456", "123"));
cart.checkout(100.0);
// 切换为PayPal支付
cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
cart.checkout(50.0);
}
}
策略模式允许在运行时动态改变对象的行为:
// 根据用户选择切换策略
if(userChoosesCreditCard()) {
cart.setPaymentStrategy(new CreditCardPayment(...));
} else {
cart.setPaymentStrategy(new PayPalPayment(...));
}
替代传统的if-else或switch-case语句:
// 传统方式
if(paymentType == CREDIT_CARD) {
processCreditCard();
} else if(paymentType == PAYPAL) {
processPayPal();
}
// 策略模式方式
paymentStrategy.process();
新增策略时无需修改现有代码:
// 新增加密货币支付策略
public class CryptoPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using Bitcoin");
}
}
// 使用新策略
cart.setPaymentStrategy(new CryptoPayment());
Comparator接口
java Collections.sort(list, new Comparator<T>() { public int compare(T o1, T o2) { return o1.compareTo(o2); // 可以替换不同的比较策略 } });
ThreadPoolExecutor的拒绝策略
java executor.setRejectedExecutionHandler( new ThreadPoolExecutor.AbortPolicy() // 可替换为其他拒绝策略 );
Java Security的加密策略
java Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
public class PaymentStrategyFactory {
public static PaymentStrategy getStrategy(PaymentType type) {
switch(type) {
case CREDIT_CARD: return new CreditCardPayment(...);
case PAYPAL: return new PayPalPayment(...);
case CRYPTO: return new CryptoPayment();
default: throw new IllegalArgumentException();
}
}
}
// 使用
PaymentStrategy strategy = PaymentStrategyFactory.getStrategy(userChoice);
@Component
public class PaymentService {
private Map<String, PaymentStrategy> strategies;
@Autowired
public PaymentService(List<PaymentStrategy> strategyList) {
strategies = strategyList.stream()
.collect(Collectors.toMap(
s -> s.getClass().getSimpleName(),
Function.identity()
));
}
public void processPayment(String strategyName, double amount) {
strategies.get(strategyName).pay(amount);
}
}
public class Calculator {
private BinaryOperator<Double> operation;
public void setStrategy(BinaryOperator<Double> strategy) {
this.operation = strategy;
}
public double calculate(double a, double b) {
return operation.apply(a, b);
}
}
// 使用
calculator.setStrategy((a, b) -> a + b); // 加法策略
calculator.setStrategy((a, b) -> a * b); // 乘法策略
虽然结构相似,但两者意图不同:
特性 | 策略模式 | 状态模式 |
---|---|---|
目的 | 灵活替换算法 | 对象内部状态改变时改变行为 |
切换方 | 客户端或上下文决定 | 由状态实现类自行控制状态转移 |
关注点 | 不同算法的实现 | 状态转换和状态相关行为 |
生命周期 | 策略通常独立于上下文 | 状态与上下文生命周期紧密相关 |
策略模式是处理“怎么做”的问题,而状态模式是处理“是什么状态”的问题。