策略模式:算法的自由王国
摘要
策略模式是行为型设计模式中的"算法封装大师",它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。本文将深入探讨策略模式的核心思想、实现方式、应用场景及高级变体,通过丰富的Java代码示例展示如何构建灵活可扩展的算法系统,并分析其与状态模式、模板方法模式的区别与适用场景。
一、策略模式核心思想
策略模式的核心是分离算法定义与使用,具有以下关键特征:
- 算法封装:每个算法被封装在独立的策略类中
- 动态切换:运行时可以自由切换不同策略
- 消除条件分支:避免复杂的if-else或switch-case语句
- 开闭原则:新增算法无需修改现有代码
适用场景:
- 系统需要在多种算法间动态切换
- 需要避免使用多重条件选择语句
- 算法需要独立于使用它们的客户端
- 需要隐藏算法实现细节
二、策略模式结构解析
UML类图示意
[Context] o--> [Strategy]
[Strategy] <|-- [ConcreteStrategyA]
[Strategy] <|-- [ConcreteStrategyB]
[Strategy] <|-- [ConcreteStrategyC]
核心组件角色
| 角色 | 职责 | 典型实现 |
|---|---|---|
| Strategy | 策略接口 | 定义算法方法的接口 |
| ConcreteStrategy | 具体策略 | 实现策略接口的具体算法类 |
| Context | 上下文 | 持有策略引用并执行算法 |
三、基础实现:支付系统案例
// 策略接口:支付策略
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略:信用卡支付
class CreditCardStrategy implements PaymentStrategy {
private String cardNumber;
private String cvv;
public CreditCardStrategy(String cardNumber, String cvv) {
this.cardNumber = cardNumber;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.printf("Paying %.2f with credit card: %s\n", amount, maskCardNumber());
}
private String maskCardNumber() {
return "****-****-****-" + cardNumber.substring(12);
}
}
// 具体策略:PayPal支付
class PayPalStrategy implements PaymentStrategy {
private String email;
public PayPalStrategy(String email) {
this.email = email;
}
@Override
public void pay(double amount) {
System.out.printf("Paying %.2f with PayPal account: %s\n", amount, email);
}
}
// 具体策略:加密货币支付
class CryptoStrategy implements PaymentStrategy {
private String walletAddress;
public CryptoStrategy(String walletAddress) {
this.walletAddress = walletAddress;
}
@Override
public void pay(double amount) {
System.out.printf("Paying %.2f with cryptocurrency to: %s\n", amount, walletAddress);
}
}
// 上下文:购物车
class ShoppingCart {
private PaymentStrategy paymentStrategy;
private List<Item> items = new ArrayList<>();
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void addItem(Item item) {
items.add(item);
}
public void checkout() {
double total = calculateTotal();
paymentStrategy.pay(total);
}
private double calculateTotal() {
return items.stream().mapToDouble(Item::getPrice).sum();
}
}
// 客户端使用
public class PaymentDemo {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.addItem(new Item("Laptop", 1200));
cart.addItem(new Item("Headphones", 150));
// 选择支付策略
cart.setPaymentStrategy(new CreditCardStrategy("1234567812345678", "123"));
cart.checkout();
// 切换支付策略
cart.setPaymentStrategy(new PayPalStrategy("user@example.com"));
cart.checkout();
// 切换支付策略
cart.setPaymentStrategy(new CryptoStrategy("0x742d35Cc6634C0532925a3b844Bc454e4438f44e"));
cart.checkout();
}
}
四、高级应用:动态算法选择
1. 策略工厂模式
class StrategyFactory {
private Map<String, PaymentStrategy> strategies = new HashMap<>();
public StrategyFactory() {
// 注册默认策略
registerStrategy("credit", (card, cvv) -> new CreditCardStrategy(card, cvv));
registerStrategy("paypal", (email, _) -> new PayPalStrategy(email));
registerStrategy("crypto", (address, _) -> new CryptoStrategy(address));
}
public void registerStrategy(String type, BiFunction<String, String, PaymentStrategy> creator) {
strategies.put(type, creator);
}
public PaymentStrategy getStrategy(String type, String param1, String param2) {
PaymentStrategy strategy = strategies.get(type);
if (strategy == null) {
throw new IllegalArgumentException("Unknown strategy type: " + type);
}
return strategy;
}
}
// 使用示例
StrategyFactory factory = new StrategyFactory();
PaymentStrategy strategy = factory.getStrategy("credit", "1234567812345678", "123");
2. 策略组合
// 组合策略
class CompositeStrategy implements PaymentStrategy {
private List<PaymentStrategy> strategies;
private double[] ratios;
public CompositeStrategy(List<PaymentStrategy> strategies, double[] ratios) {
this.strategies = strategies;
this.ratios = ratios;
}
@Override
public void pay(double totalAmount) {
for (int i = 0; i < strategies.size(); i++) {
double amount = totalAmount * ratios[i];
strategies.get(i).pay(amount);
}
}
}
// 使用示例
PaymentStrategy credit = new CreditCardStrategy("1234567812345678", "123");
PaymentStrategy paypal = new PayPalStrategy("user@example.com");
CompositeStrategy splitPayment = new CompositeStrategy(
Arrays.asList(credit, paypal),
new double[]{0.7, 0.3} // 70%信用卡,30%PayPal
);
cart.setPaymentStrategy(splitPayment);
cart.checkout();
五、策略模式在复杂系统中的应用
1. 电商定价系统
// 定价策略接口
interface PricingStrategy {
double calculatePrice(Product product, int quantity);
}
// 具体策略:标准定价
class StandardPricing implements PricingStrategy {
public double calculatePrice(Product product, int quantity) {
return product.getBasePrice() * quantity;
}
}
// 具体策略:批量折扣
class BulkDiscountPricing implements PricingStrategy {
private int threshold;
private double discountRate;
public BulkDiscountPricing(int threshold, double discountRate) {
this.threshold = threshold;
this.discountRate = discountRate;
}
public double calculatePrice(Product product, int quantity) {
double basePrice = product.getBasePrice();
if (quantity >= threshold) {
return basePrice * quantity * (1 - discountRate);
}
return basePrice * quantity;
}
}
// 具体策略:会员定价
class MemberPricing implements PricingStrategy {
private double memberDiscount;
public MemberPricing(double memberDiscount) {
this.memberDiscount = memberDiscount;
}
public double calculatePrice(Product product, int quantity) {
return product.getBasePrice() * quantity * (1 - memberDiscount);
}
}
// 定价上下文
class PricingContext {
private PricingStrategy strategy;
public void setStrategy(PricingStrategy strategy) {
this.strategy = strategy;
}
public double calculateTotal(Order order) {
double total = 0;
for (OrderItem item : order.getItems()) {
total += strategy.calculatePrice(item.getProduct(), item.getQuantity());
}
return total;
}
}
// 使用示例
Order order = getCurrentOrder();
PricingContext context = new PricingContext();
// 普通用户使用标准定价
context.setStrategy(new StandardPricing());
double standardTotal = context.calculateTotal(order);
// 批量采购用户
context.setStrategy(new BulkDiscountPricing(10, 0.15));
double bulkTotal = context.calculateTotal(order);
// 会员用户
context.setStrategy(new MemberPricing(0.1));
double memberTotal = context.calculateTotal(order);
2. 游戏AI行为系统
// AI行为策略
interface AIBehavior {
void performAction(GameCharacter character, GameContext context);
}
// 攻击行为
class AggressiveBehavior implements AIBehavior {
public void performAction(GameCharacter character, GameContext context) {
Character target = findNearestEnemy(character, context);
if (target != null) {
character.attack(target);
} else {
character.moveToRandomPosition();
}
}
}
// 防御行为
class DefensiveBehavior implements AIBehavior {
public void performAction(GameCharacter character, GameContext context) {
if (character.getHealth() < 30) {
character.useHealingItem();
} else {
character.defend();
}
}
}
// 逃跑行为
class FleeingBehavior implements AIBehavior {
public void performAction(GameCharacter character, GameContext context) {
if (character.getHealth() < 20) {
character.moveToSafeZone();
} else {
// 低概率随机移动
if (Math.random() < 0.3) {
character.moveToRandomPosition();
}
}
}
}
// AI控制器
class AIController {
private AIBehavior currentBehavior;
public void setBehavior(AIBehavior behavior) {
this.currentBehavior = behavior;
}
public void update(GameCharacter character, GameContext context) {
currentBehavior.performAction(character, context);
}
}
// 使用示例
GameCharacter enemy = new GameCharacter();
AIController ai = new AIController();
// 根据情境切换行为
if (enemy.getHealth() > 70) {
ai.setBehavior(new AggressiveBehavior());
} else if (enemy.getHealth() > 30) {
ai.setBehavior(new DefensiveBehavior());
} else {
ai.setBehavior(new FleeingBehavior());
}
// 游戏循环中
while (gameRunning) {
ai.update(enemy, gameContext);
// 其他游戏逻辑...
}
六、策略模式优缺点分析
优点:
| 优点 | 说明 |
|---|---|
| 开闭原则 | 新增策略无需修改现有代码 |
| 消除条件语句 | 避免复杂的条件分支 |
| 算法复用 | 策略可在不同上下文中复用 |
| 运行时切换 | 动态改变对象行为 |
| 算法封装 | 隐藏实现细节,提高内聚性 |
缺点:
| 缺点 | 说明 |
|---|---|
| 类数量增加 | 每个策略都需要单独类 |
| 客户端需了解策略 | 客户端需知道不同策略的区别 |
| 通信开销 | 策略间共享数据需通过上下文 |
| 过度设计风险 | 简单算法可能不需要策略模式 |
七、策略模式与其他模式对比
策略模式 vs 状态模式
| 维度 | 策略模式 | 状态模式 |
|---|---|---|
| 目的 | 封装算法 | 管理状态转换 |
| 切换机制 | 客户端显式切换 | 状态自动转换 |
| 关注点 | 算法实现 | 状态行为 |
| 依赖关系 | 策略相互独立 | 状态相互了解 |
策略模式 vs 模板方法模式
| 维度 | 策略模式 | 模板方法模式 |
|---|---|---|
| 实现方式 | 组合 | 继承 |
| 扩展点 | 完整算法替换 | 算法步骤扩展 |
| 灵活性 | 运行时切换 | 编译时确定 |
| 代码复用 | 策略对象复用 | 父类代码复用 |
八、策略模式最佳实践
1. 策略枚举实现
enum CalculatorStrategy implements DoubleBinaryOperator {
ADD {
public double applyAsDouble(double a, double b) {
return a + b;
}
},
SUBTRACT {
public double applyAsDouble(double a, double b) {
return a - b;
}
},
MULTIPLY {
public double applyAsDouble(double a, double b) {
return a * b;
}
},
DIVIDE {
public double applyAsDouble(double a, double b) {
if (b == 0) throw new ArithmeticException("Division by zero");
return a / b;
}
};
}
// 使用示例
double result = CalculatorStrategy.ADD.applyAsDouble(5, 3); // 8.0
2. 策略与Lambda表达式
class TextProcessor {
private Function<String, String> processingStrategy;
public TextProcessor() {
// 默认策略:无操作
this.processingStrategy = Function.identity();
}
public void setProcessingStrategy(Function<String, String> strategy) {
this.processingStrategy = strategy;
}
public String processText(String input) {
return processingStrategy.apply(input);
}
}
// 使用示例
TextProcessor processor = new TextProcessor();
// 设置大写转换策略
processor.setProcessingStrategy(String::toUpperCase);
System.out.println(processor.processText("hello")); // HELLO
// 设置反转策略
processor.setProcessingStrategy(s -> new StringBuilder(s).reverse().toString());
System.out.println(processor.processText("hello")); // olleh
// 设置自定义策略
processor.setProcessingStrategy(s -> s.replaceAll("l", "L"));
System.out.println(processor.processText("hello")); // heLLo
3. 策略缓存与重用
class StrategyCache {
private Map<String, PricingStrategy> cache = new HashMap<>();
public PricingStrategy getStrategy(String strategyType) {
return cache.computeIfAbsent(strategyType, type -> {
switch (type) {
case "standard": return new StandardPricing();
case "bulk": return new BulkDiscountPricing(10, 0.15);
case "member": return new MemberPricing(0.1);
default: throw new IllegalArgumentException("Unknown strategy");
}
});
}
}
// 使用示例
StrategyCache strategyCache = new StrategyCache();
PricingStrategy bulkStrategy = strategyCache.getStrategy("bulk");
九、策略模式在开源框架中的应用
Spring框架中的策略模式
// Spring的资源加载策略
ResourceLoader loader = new DefaultResourceLoader();
Resource resource = loader.getResource("classpath:config.xml");
// 内部实现:不同资源位置的策略
public interface ResourcePatternResolver {
Resource[] getResources(String locationPattern) throws IOException;
}
// 具体策略实现
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
// 实现资源匹配算法
}
Java Collections排序策略
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用不同排序策略
Collections.sort(names); // 自然顺序
Collections.sort(names, Collections.reverseOrder()); // 逆序
Collections.sort(names, String.CASE_INSENSITIVE_ORDER); // 忽略大小写
// 自定义排序策略
Collections.sort(names, (a, b) -> b.length() - a.length()); // 按长度降序
十、策略模式演进:函数式策略
函数式接口作为策略
@FunctionalInterface
interface ValidationStrategy {
boolean validate(String input);
}
class Validator {
private ValidationStrategy strategy;
public Validator(ValidationStrategy strategy) {
this.strategy = strategy;
}
public boolean validate(String input) {
return strategy.validate(input);
}
}
// 使用示例
Validator numericValidator = new Validator(s -> s.matches("\\d+"));
boolean isNumeric = numericValidator.validate("12345"); // true
Validator emailValidator = new Validator(s -> s.matches("[a-z]+@[a-z]+\\.[a-z]{2,3}"));
boolean isEmail = emailValidator.validate("user@example.com"); // true
策略组合与管道
class ValidationPipeline {
private List<ValidationStrategy> strategies = new ArrayList<>();
public ValidationPipeline addStrategy(ValidationStrategy strategy) {
strategies.add(strategy);
return this;
}
public boolean validate(String input) {
for (ValidationStrategy strategy : strategies) {
if (!strategy.validate(input)) {
return false;
}
}
return true;
}
}
// 使用示例
ValidationPipeline pipeline = new ValidationPipeline()
.addStrategy(s -> s.length() >= 8) // 最小长度
.addStrategy(s -> s.matches(".*[A-Z].*")) // 包含大写字母
.addStrategy(s -> s.matches(".*[0-9].*")); // 包含数字
boolean isValid = pipeline.validate("Password123"); // true
总结
策略模式是构建灵活算法系统的核心设计模式,它通过以下方式提升系统质量:
- 解耦算法:将算法从业务逻辑中分离
- 提升扩展性:新增算法不影响现有代码
- 增强可维护性:消除复杂条件分支
- 支持运行时决策:动态切换不同策略
现代应用趋势:
- 函数式策略:Lambda表达式简化策略实现
- 策略自动选择:基于规则的策略选择机制
- 策略组合:构建复杂行为管道
- 微服务策略:分布式系统中的策略服务
在应用策略模式时需注意:
- 避免过度细分:合理确定策略粒度
- 策略管理:使用工厂模式管理策略创建
- 上下文设计:合理设计策略与上下文的交互
- 性能考量:高频切换策略时的性能影响
策略模式是现代软件架构中不可或缺的设计工具,特别是在需要灵活算法和业务规则的系统中。掌握策略模式的精髓,将帮助开发者构建出更加灵活、可扩展和易维护的系统架构。
















