策略设计模式全方位深度解析

3 阅读13分钟

一、模式定义与核心思想

1.1 模式定义

策略模式(Strategy Pattern)是一种行为型设计模式,定义一系列算法,将每个算法封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

1.2 核心思想

  1. 封装变化:将易变的算法部分独立出来
  2. 面向接口编程:定义策略接口,具体实现可互换
  3. 组合优于继承:通过组合策略对象,避免继承导致的类爆炸

二、模式结构详解

2.1 UML类图

复制
┌─────────────────┐          ┌─────────────────┐
│   Context       │          │   Strategy      │
├────────────────-┤          ├────────────────-┤
│ -strategy       │<>------->│ +execute():void │
├────────────────-┤          └─────────────────┘
│ +setStrategy()  │                     ^
│ +execute()      │                     │
└─────────────────┘          ┌─────────────────────┐
                             │                     │
               ┌─────────────┴──────┐ ┌────────────┴─────────┐
               │ ConcreteStrategyA  │ │ ConcreteStrategyB    │
               ├────────────────────-┤ ├──────────────────────┤
               │ +execute():void    │ │ +execute():void      │
               └────────────────────-┘ └──────────────────────┘

2.2 核心角色

  • Context:上下文,持有策略引用
  • Strategy:策略接口
  • ConcreteStrategy:具体策略实现

三、Java实现详解

3.1 基础实现框架

java
java
下载
复制
// 1. 策略接口
public interface PaymentStrategy {
    /**
     * 支付方法
     * @param amount 支付金额
     * @return 支付结果
     */
    PaymentResult pay(BigDecimal amount);
    
    /**
     * 获取策略名称
     * @return 策略名称
     */
    String getStrategyName();
    
    /**
     * 是否支持该支付方式
     * @return 是否支持
     */
    boolean isSupported();
}

// 2. 支付结果类
public class PaymentResult {
    private boolean success;
    private String transactionId;
    private String message;
    private LocalDateTime payTime;
    private BigDecimal actualAmount;
    
    // 构造器、getter、setter
    public PaymentResult(boolean success, String transactionId, String message) {
        this.success = success;
        this.transactionId = transactionId;
        this.message = message;
        this.payTime = LocalDateTime.now();
    }
    
    // builder模式
    public static PaymentResultBuilder builder() {
        return new PaymentResultBuilder();
    }
    
    public static class PaymentResultBuilder {
        private boolean success;
        private String transactionId;
        private String message;
        private BigDecimal actualAmount;
        
        public PaymentResultBuilder success(boolean success) {
            this.success = success;
            return this;
        }
        
        public PaymentResultBuilder transactionId(String transactionId) {
            this.transactionId = transactionId;
            return this;
        }
        
        public PaymentResultBuilder message(String message) {
            this.message = message;
            return this;
        }
        
        public PaymentResultBuilder actualAmount(BigDecimal amount) {
            this.actualAmount = amount;
            return this;
        }
        
        public PaymentResult build() {
            PaymentResult result = new PaymentResult(success, transactionId, message);
            result.setActualAmount(actualAmount);
            return result;
        }
    }
    
    // getters and setters
    // ...
}

3.2 具体策略实现

3.2.1 信用卡支付策略

java
java
下载
复制
public class CreditCardPaymentStrategy implements PaymentStrategy {
    private final String cardNumber;
    private final String cardHolder;
    private final String expiryDate;
    private final String cvv;
    private final boolean enable3DSecure;
    
    public CreditCardPaymentStrategy(String cardNumber, String cardHolder, 
                                    String expiryDate, String cvv) {
        this(cardNumber, cardHolder, expiryDate, cvv, true);
    }
    
    public CreditCardPaymentStrategy(String cardNumber, String cardHolder,
                                    String expiryDate, String cvv, 
                                    boolean enable3DSecure) {
        validateCardDetails(cardNumber, expiryDate, cvv);
        this.cardNumber = cardNumber;
        this.cardHolder = cardHolder;
        this.expiryDate = expiryDate;
        this.cvv = cvv;
        this.enable3DSecure = enable3DSecure;
    }
    
    private void validateCardDetails(String cardNumber, String expiryDate, String cvv) {
        if (cardNumber == null || !cardNumber.matches("\d{13,19}")) {
            throw new IllegalArgumentException("Invalid card number");
        }
        if (expiryDate == null || !expiryDate.matches("(0[1-9]|1[0-2])/[0-9]{2}")) {
            throw new IllegalArgumentException("Invalid expiry date format (MM/YY)");
        }
        if (cvv == null || !cvv.matches("\d{3,4}")) {
            throw new IllegalArgumentException("Invalid CVV");
        }
    }
    
    @Override
    public PaymentResult pay(BigDecimal amount) {
        System.out.println("使用信用卡支付: " + cardNumber);
        System.out.println("持卡人: " + cardHolder);
        System.out.println("支付金额: $" + amount);
        
        // 模拟3D安全验证
        if (enable3DSecure) {
            System.out.println("进行3D安全验证...");
            if (!perform3DSecureVerification()) {
                return PaymentResult.builder()
                    .success(false)
                    .message("3D Secure验证失败")
                    .build();
            }
        }
        
        // 模拟银行API调用
        boolean paymentSuccess = processCreditCardPayment(amount);
        
        if (paymentSuccess) {
            String transactionId = "CC" + System.currentTimeMillis() + 
                                  cardNumber.substring(cardNumber.length() - 4);
            return PaymentResult.builder()
                .success(true)
                .transactionId(transactionId)
                .message("信用卡支付成功")
                .actualAmount(amount)
                .build();
        } else {
            return PaymentResult.builder()
                .success(false)
                .message("信用卡支付失败: 余额不足或卡片被拒")
                .build();
        }
    }
    
    private boolean perform3DSecureVerification() {
        // 模拟3D安全验证
        return Math.random() > 0.1; // 90%成功率
    }
    
    private boolean processCreditCardPayment(BigDecimal amount) {
        // 模拟银行支付处理
        // 实际项目中这里会调用银行API
        try {
            Thread.sleep(100); // 模拟网络延迟
            return Math.random() > 0.2; // 80%成功率
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    @Override
    public String getStrategyName() {
        return "CREDIT_CARD";
    }
    
    @Override
    public boolean isSupported() {
        // 检查卡片是否在有效期内
        LocalDate expiry = parseExpiryDate(expiryDate);
        return !expiry.isBefore(LocalDate.now());
    }
    
    private LocalDate parseExpiryDate(String expiryDate) {
        String[] parts = expiryDate.split("/");
        int month = Integer.parseInt(parts[0]);
        int year = 2000 + Integer.parseInt(parts[1]);
        return LocalDate.of(year, month, 1).withDayOfMonth(
            YearMonth.of(year, month).lengthOfMonth()
        );
    }
}

3.2.2 PayPal支付策略

java
java
下载
复制
public class PayPalPaymentStrategy implements PaymentStrategy {
    private final String email;
    private final String password;
    private String accessToken;
    private LocalDateTime tokenExpiryTime;
    
    public PayPalPaymentStrategy(String email, String password) {
        this.email = email;
        this.password = password;
    }
    
    @Override
    public PaymentResult pay(BigDecimal amount) {
        System.out.println("使用PayPal支付");
        System.out.println("PayPal账户: " + email);
        
        // 获取访问令牌
        if (!authenticate()) {
            return PaymentResult.builder()
                .success(false)
                .message("PayPal认证失败")
                .build();
        }
        
        // 检查余额
        BigDecimal balance = getPayPalBalance();
        if (balance.compareTo(amount) < 0) {
            return PaymentResult.builder()
                .success(false)
                .message("PayPal余额不足,当前余额: $" + balance)
                .build();
        }
        
        // 执行支付
        boolean paymentSuccess = processPayPalPayment(amount);
        
        if (paymentSuccess) {
            String transactionId = "PP" + System.currentTimeMillis() + 
                                  email.hashCode();
            return PaymentResult.builder()
                .success(true)
                .transactionId(transactionId)
                .message("PayPal支付成功")
                .actualAmount(amount)
                .build();
        } else {
            return PaymentResult.builder()
                .success(false)
                .message("PayPal支付失败")
                .build();
        }
    }
    
    private boolean authenticate() {
        // 如果令牌有效,直接返回
        if (accessToken != null && tokenExpiryTime != null && 
            tokenExpiryTime.isAfter(LocalDateTime.now())) {
            return true;
        }
        
        // 模拟PayPal OAuth认证
        System.out.println("正在认证PayPal账户...");
        try {
            Thread.sleep(200); // 模拟网络延迟
            
            // 模拟认证
            if (isValidCredentials(email, password)) {
                accessToken = "PP_TOKEN_" + UUID.randomUUID();
                tokenExpiryTime = LocalDateTime.now().plusHours(1);
                return true;
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return false;
    }
    
    private boolean isValidCredentials(String email, String password) {
        // 简化验证逻辑
        return email.contains("@") && password.length() >= 6;
    }
    
    private BigDecimal getPayPalBalance() {
        // 模拟获取余额
        return new BigDecimal("1000.00"); // 模拟固定余额
    }
    
    private boolean processPayPalPayment(BigDecimal amount) {
        // 模拟PayPal支付处理
        try {
            Thread.sleep(150);
            return Math.random() > 0.15; // 85%成功率
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
    
    @Override
    public String getStrategyName() {
        return "PAYPAL";
    }
    
    @Override
    public boolean isSupported() {
        // PayPal通常全球支持
        return true;
    }
}

3.2.3 加密货币支付策略

java
java
下载
复制
public class CryptocurrencyPaymentStrategy implements PaymentStrategy {
    private final String walletAddress;
    private final CryptoCurrency currency;
    private final BigDecimal gasLimit; // Gas限制
    private final BigDecimal gasPrice;  // Gas价格
    
    public enum CryptoCurrency {
        BITCOIN("BTC", "比特币", 6),
        ETHEREUM("ETH", "以太坊", 18),
        USDT("USDT", "泰达币", 6);
        
        private final String symbol;
        private final String name;
        private final int decimals;
        
        CryptoCurrency(String symbol, String name, int decimals) {
            this.symbol = symbol;
            this.name = name;
            this.decimals = decimals;
        }
        
        public String getSymbol() { return symbol; }
        public String getName() { return name; }
        public int getDecimals() { return decimals; }
    }
    
    public CryptocurrencyPaymentStrategy(String walletAddress, CryptoCurrency currency) {
        this(walletAddress, currency, 
             new BigDecimal("21000"), new BigDecimal("20"));
    }
    
    public CryptocurrencyPaymentStrategy(String walletAddress, CryptoCurrency currency,
                                        BigDecimal gasLimit, BigDecimal gasPrice) {
        validateWalletAddress(walletAddress, currency);
        this.walletAddress = walletAddress;
        this.currency = currency;
        this.gasLimit = gasLimit;
        this.gasPrice = gasPrice;
    }
    
    private void validateWalletAddress(String address, CryptoCurrency currency) {
        if (address == null || address.trim().isEmpty()) {
            throw new IllegalArgumentException("钱包地址不能为空");
        }
        
        switch (currency) {
            case BITCOIN:
                if (!address.matches("^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$")) {
                    throw new IllegalArgumentException("无效的比特币地址");
                }
                break;
            case ETHEREUM:
                if (!address.matches("^0x[a-fA-F0-9]{40}$")) {
                    throw new IllegalArgumentException("无效的以太坊地址");
                }
                break;
            case USDT:
                if (!address.matches("^T[a-zA-Z0-9]{33}$")) {
                    throw new IllegalArgumentException("无效的USDT地址");
                }
                break;
        }
    }
    
    @Override
    public PaymentResult pay(BigDecimal amount) {
        System.out.println("使用" + currency.getName() + "支付");
        System.out.println("钱包地址: " + walletAddress);
        System.out.println("支付金额: " + amount + " " + currency.getSymbol());
        
        // 计算矿工费
        BigDecimal gasFee = calculateGasFee();
        BigDecimal totalAmount = amount.add(gasFee);
        
        System.out.println("矿工费: " + gasFee + " Gwei");
        System.out.println("总计: " + totalAmount + " " + currency.getSymbol());
        
        // 检查余额
        BigDecimal balance = getWalletBalance();
        if (balance.compareTo(totalAmount) < 0) {
            return PaymentResult.builder()
                .success(false)
                .message("余额不足,当前余额: " + balance + " " + currency.getSymbol())
                .build();
        }
        
        // 构建交易
        String transactionHash = buildTransaction(amount, gasFee);
        
        if (transactionHash != null) {
            return PaymentResult.builder()
                .success(true)
                .transactionId(transactionHash)
                .message(currency.getName() + "支付成功")
                .actualAmount(amount)
                .build();
        } else {
            return PaymentResult.builder()
                .success(false)
                .message(currency.getName() + "交易失败")
                .build();
        }
    }
    
    private BigDecimal calculateGasFee() {
        // 计算矿工费: gasLimit * gasPrice
        return gasLimit.multiply(gasPrice)
                      .divide(new BigDecimal("1000000000")); // 转换为Gwei
    }
    
    private BigDecimal getWalletBalance() {
        // 模拟获取钱包余额
        // 实际项目中会调用区块链API
        return new BigDecimal("5.0"); // 5个币
    }
    
    private String buildTransaction(BigDecimal amount, BigDecimal gasFee) {
        // 模拟构建区块链交易
        try {
            System.out.println("构建" + currency.getName() + "交易...");
            Thread.sleep(500); // 模拟区块链网络延迟
            
            // 模拟交易失败(网络拥堵等)
            if (Math.random() < 0.1) {
                System.out.println("交易失败: 网络拥堵");
                return null;
            }
            
            // 生成交易哈希
            String hash = "0x" + UUID.randomUUID().toString().replace("-", "");
            System.out.println("交易已广播,哈希: " + hash);
            System.out.println("等待确认...");
            
            // 模拟区块确认
            for (int i = 1; i <= 3; i++) {
                Thread.sleep(1000);
                System.out.println("第" + i + "个区块确认");
            }
            
            return hash;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        }
    }
    
    @Override
    public String getStrategyName() {
        return "CRYPTO_" + currency.getSymbol();
    }
    
    @Override
    public boolean isSupported() {
        // 检查网络连接和钱包状态
        return checkNetworkConnection() && checkWalletStatus();
    }
    
    private boolean checkNetworkConnection() {
        // 模拟网络检查
        return Math.random() > 0.2; // 80%网络可用
    }
    
    private boolean checkWalletStatus() {
        // 模拟钱包状态检查
        return true;
    }
}

3.3 策略工厂模式

java
java
下载
复制
// 策略工厂
public class PaymentStrategyFactory {
    private static final Map<String, PaymentStrategy> strategies = new ConcurrentHashMap<>();
    private static final Map<String, StrategyConfig> strategyConfigs = new ConcurrentHashMap<>();
    
    static {
        // 加载配置文件中的策略配置
        loadStrategyConfigs();
    }
    
    public static PaymentStrategy getStrategy(String strategyType, 
                                            Map<String, Object> params) {
        // 检查缓存
        String cacheKey = buildCacheKey(strategyType, params);
        if (strategies.containsKey(cacheKey)) {
            return strategies.get(cacheKey);
        }
        
        PaymentStrategy strategy = createStrategy(strategyType, params);
        strategies.put(cacheKey, strategy);
        return strategy;
    }
    
    private static PaymentStrategy createStrategy(String strategyType, 
                                                Map<String, Object> params) {
        StrategyConfig config = strategyConfigs.get(strategyType);
        if (config == null) {
            throw new IllegalArgumentException("不支持的支付策略: " + strategyType);
        }
        
        if (!config.isEnabled()) {
            throw new IllegalStateException("支付策略已被禁用: " + strategyType);
        }
        
        // 验证必填参数
        validateRequiredParams(strategyType, params, config.getRequiredParams());
        
        switch (strategyType.toUpperCase()) {
            case "CREDIT_CARD":
                return new CreditCardPaymentStrategy(
                    (String) params.get("cardNumber"),
                    (String) params.get("cardHolder"),
                    (String) params.get("expiryDate"),
                    (String) params.get("cvv"),
                    (Boolean) params.getOrDefault("enable3DSecure", true)
                );
                
            case "PAYPAL":
                return new PayPalPaymentStrategy(
                    (String) params.get("email"),
                    (String) params.get("password")
                );
                
            case "CRYPTO_BTC":
                return new CryptocurrencyPaymentStrategy(
                    (String) params.get("walletAddress"),
                    CryptocurrencyPaymentStrategy.CryptoCurrency.BITCOIN
                );
                
            case "CRYPTO_ETH":
                return new CryptocurrencyPaymentStrategy(
                    (String) params.get("walletAddress"),
                    CryptocurrencyPaymentStrategy.CryptoCurrency.ETHEREUM
                );
                
            case "ALIPAY":
                return new AlipayPaymentStrategy(
                    (String) params.get("alipayAccount")
                );
                
            case "WECHAT_PAY":
                return new WeChatPaymentStrategy(
                    (String) params.get("openId")
                );
                
            default:
                throw new IllegalArgumentException("未知支付策略: " + strategyType);
        }
    }
    
    private static void validateRequiredParams(String strategyType, 
                                              Map<String, Object> params,
                                              Set<String> requiredParams) {
        for (String param : requiredParams) {
            if (!params.containsKey(param) || params.get(param) == null) {
                throw new IllegalArgumentException(
                    "参数 '" + param + "' 是必需的,对于策略: " + strategyType
                );
            }
        }
    }
    
    private static String buildCacheKey(String strategyType, Map<String, Object> params) {
        StringBuilder key = new StringBuilder(strategyType);
        params.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .forEach(entry -> 
                key.append("_").append(entry.getKey()).append(":").append(entry.getValue())
            );
        return key.toString();
    }
    
    private static void loadStrategyConfigs() {
        // 从配置文件或数据库加载策略配置
        strategyConfigs.put("CREDIT_CARD", 
            new StrategyConfig(true, 
                Set.of("cardNumber", "cardHolder", "expiryDate", "cvv"))
        );
        strategyConfigs.put("PAYPAL", 
            new StrategyConfig(true, Set.of("email", "password"))
        );
        strategyConfigs.put("CRYPTO_BTC", 
            new StrategyConfig(true, Set.of("walletAddress"))
        );
        strategyConfigs.put("CRYPTO_ETH", 
            new StrategyConfig(true, Set.of("walletAddress"))
        );
        strategyConfigs.put("ALIPAY", 
            new StrategyConfig(true, Set.of("alipayAccount"))
        );
        strategyConfigs.put("WECHAT_PAY", 
            new StrategyConfig(true, Set.of("openId"))
        );
    }
    
    // 策略配置类
    private static class StrategyConfig {
        private boolean enabled;
        private Set<String> requiredParams;
        
        public StrategyConfig(boolean enabled, Set<String> requiredParams) {
            this.enabled = enabled;
            this.requiredParams = requiredParams;
        }
        
        public boolean isEnabled() { return enabled; }
        public Set<String> getRequiredParams() { return requiredParams; }
    }
}

3.4 上下文类实现

java
java
下载
复制
// 支付上下文
public class PaymentContext {
    private PaymentStrategy paymentStrategy;
    private String orderId;
    private BigDecimal amount;
    private String currency = "CNY";
    private PaymentContextState state = PaymentContextState.INITIALIZED;
    
    public enum PaymentContextState {
        INITIALIZED,
        STRATEGY_SELECTED,
        VALIDATING,
        PROCESSING,
        SUCCESS,
        FAILED,
        CANCELLED
    }
    
    public PaymentContext(String orderId, BigDecimal amount) {
        this.orderId = orderId;
        this.amount = amount;
    }
    
    public PaymentContext(String orderId, BigDecimal amount, String currency) {
        this(orderId, amount);
        this.currency = currency;
    }
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        if (strategy == null) {
            throw new IllegalArgumentException("支付策略不能为空");
        }
        
        if (!strategy.isSupported()) {
            throw new IllegalStateException("支付策略不支持: " + strategy.getStrategyName());
        }
        
        this.paymentStrategy = strategy;
        this.state = PaymentContextState.STRATEGY_SELECTED;
        System.out.println("支付策略已设置: " + strategy.getStrategyName());
    }
    
    public PaymentResult executePayment() {
        validatePayment();
        
        try {
            state = PaymentContextState.PROCESSING;
            System.out.println("开始处理订单支付: " + orderId);
            System.out.println("支付金额: " + amount + " " + currency);
            
            PaymentResult result = paymentStrategy.pay(amount);
            
            if (result.isSuccess()) {
                state = PaymentContextState.SUCCESS;
                System.out.println("支付成功! 交易号: " + result.getTransactionId());
            } else {
                state = PaymentContextState.FAILED;
                System.out.println("支付失败: " + result.getMessage());
            }
            
            return result;
            
        } catch (Exception e) {
            state = PaymentContextState.FAILED;
            System.out.println("支付过程异常: " + e.getMessage());
            return PaymentResult.builder()
                .success(false)
                .message("支付异常: " + e.getMessage())
                .build();
        }
    }
    
    private void validatePayment() {
        if (state == PaymentContextState.INITIALIZED) {
            throw new IllegalStateException("请先设置支付策略");
        }
        
        if (paymentStrategy == null) {
            throw new IllegalStateException("支付策略未设置");
        }
        
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("支付金额必须大于0");
        }
        
        state = PaymentContextState.VALIDATING;
    }
    
    public void cancelPayment() {
        if (state == PaymentContextState.SUCCESS) {
            throw new IllegalStateException("支付已完成,无法取消");
        }
        
        state = PaymentContextState.CANCELLED;
        System.out.println("支付已取消: " + orderId);
    }
    
    // 支持策略链
    public PaymentResult executeWithFallback(List<PaymentStrategy> fallbackStrategies) {
        PaymentResult result = null;
        List<PaymentStrategy> allStrategies = new ArrayList<>();
        allStrategies.add(paymentStrategy);
        allStrategies.addAll(fallbackStrategies);
        
        for (PaymentStrategy strategy : allStrategies) {
            try {
                System.out.println("尝试支付策略: " + strategy.getStrategyName());
                setPaymentStrategy(strategy);
                result = executePayment();
                
                if (result.isSuccess()) {
                    break;
                }
            } catch (Exception e) {
                System.out.println("策略 " + strategy.getStrategyName() + 
                                 " 执行失败: " + e.getMessage());
            }
        }
        
        return result != null ? result : 
            PaymentResult.builder()
                .success(false)
                .message("所有支付策略都失败")
                .build();
    }
    
    // Getters
    public PaymentContextState getState() { return state; }
    public String getOrderId() { return orderId; }
    public BigDecimal getAmount() { return amount; }
    public String getCurrency() { return currency; }
}

3.5 客户端使用示例

java
java
下载
复制
public class StrategyPatternDemo {
    
    public static void main(String[] args) {
        // 示例1: 基础使用
        System.out.println("=== 示例1: 基础策略模式使用 ===");
        demoBasicStrategy();
        
        // 示例2: 策略工厂使用
        System.out.println("\n=== 示例2: 策略工厂使用 ===");
        demoStrategyFactory();
        
        // 示例3: 策略链(降级策略)
        System.out.println("\n=== 示例3: 策略链(降级策略)===");
        demoStrategyChain();
        
        // 示例4: 动态策略切换
        System.out.println("\n=== 示例4: 动态策略切换 ===");
        demoDynamicStrategySwitching();
    }
    
    private static void demoBasicStrategy() {
        // 创建支付上下文
        PaymentContext context = new PaymentContext("ORDER_001", 
            new BigDecimal("199.99"), "USD");
        
        // 使用信用卡支付
        PaymentStrategy creditCardStrategy = new CreditCardPaymentStrategy(
            "4111111111111111", 
            "JOHN DOE", 
            "12/28", 
            "123"
        );
        
        context.setPaymentStrategy(creditCardStrategy);
        PaymentResult result1 = context.executePayment();
        printResult(result1);
        
        // 切换到PayPal支付
        System.out.println("\n切换支付方式...");
        PaymentStrategy paypalStrategy = new PayPalPaymentStrategy(
            "john.doe@example.com", 
            "password123"
        );
        
        // 重新设置上下文金额
        context = new PaymentContext("ORDER_002", new BigDecimal("299.99"));
        context.setPaymentStrategy(paypalStrategy);
        PaymentResult result2 = context.executePayment();
        printResult(result2);
    }
    
    private static void demoStrategyFactory() {
        // 使用策略工厂创建支付策略
        Map<String, Object> params = new HashMap<>();
        params.put("cardNumber", "5555555555554444");
        params.put("cardHolder", "JANE DOE");
        params.put("expiryDate", "06/27");
        params.put("cvv", "456");
        params.put("enable3DSecure", true);
        
        try {
            PaymentStrategy strategy = PaymentStrategyFactory.getStrategy("CREDIT_CARD", params);
            
            PaymentContext context = new PaymentContext("ORDER_003", 
                new BigDecimal("149.99"));
            context.setPaymentStrategy(strategy);
            
            PaymentResult result = context.executePayment();
            printResult(result);
        } catch (Exception e) {
            System.err.println("支付失败: " + e.getMessage());
        }
    }
    
    private static void demoStrategyChain() {
        // 准备主策略和降级策略
        Map<String, Object> cryptoParams = new HashMap<>();
        cryptoParams.put("walletAddress", "0x742d35Cc6634C0532925a3b844Bc454e4438f44e");
        
        PaymentStrategy primaryStrategy = PaymentStrategyFactory.getStrategy(
            "CRYPTO_ETH", cryptoParams);
        
        // 准备降级策略
        Map<String, Object> creditCardParams = new HashMap<>();
        creditCardParams.put("cardNumber", "378282246310005");
        creditCardParams.put("cardHolder", "FALLBACK USER");
        creditCardParams.put("expiryDate", "08/29");
        creditCardParams.put("cvv", "789");
        
        PaymentStrategy fallbackStrategy = PaymentStrategyFactory.getStrategy(
            "CREDIT_CARD", creditCardParams);
        
        // 执行带降级的支付
        PaymentContext context = new PaymentContext("ORDER_004", 
            new BigDecimal("99.99"));
        context.setPaymentStrategy(primaryStrategy);
        
        List<PaymentStrategy> fallbacks = Collections.singletonList(fallbackStrategy);
        PaymentResult result = context.executeWithFallback(fallbacks);
        
        printResult(result);
    }
    
    private static void demoDynamicStrategySwitching() {
        // 模拟动态策略切换场景
        System.out.println("模拟智能支付路由系统...");
        
        PaymentContext context = new PaymentContext("ORDER_005", 
            new BigDecimal("89.99"));
        
        // 根据不同的条件选择策略
        String userCountry = "CN";
        BigDecimal amount = context.getAmount();
        String timeOfDay = LocalTime.now().getHour() < 12 ? "MORNING" : "AFTERNOON";
        
        PaymentStrategy selectedStrategy = null;
        
        if ("CN".equals(userCountry)) {
            if (amount.compareTo(new BigDecimal("1000")) < 0) {
                // 小额支付使用微信支付
                Map<String, Object> wechatParams = new HashMap<>();
                wechatParams.put("openId", "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");
                selectedStrategy = PaymentStrategyFactory.getStrategy(
                    "WECHAT_PAY", wechatParams);
            } else {
                // 大额支付使用支付宝
                Map<String, Object> alipayParams = new HashMap<>();
                alipayParams.put("alipayAccount", "zhangsan@alipay.com");
                selectedStrategy = PaymentStrategyFactory.getStrategy(
                    "ALIPAY", alipayParams);
            }
        } else if ("US".equals(userCountry)) {
            if ("MORNING".equals(timeOfDay)) {
                // 早上使用PayPal
                Map<String, Object> paypalParams = new HashMap<>();
                paypalParams.put("email", "user@example.com");
                paypalParams.put("password", "password123");
                selectedStrategy = PaymentStrategyFactory.getStrategy(
                    "PAYPAL", paypalParams);
            } else {
                // 其他时间使用信用卡
                Map<String, Object> creditCardParams = new HashMap<>();
                creditCardParams.put("cardNumber", "4111111111111111");
                creditCardParams.put("cardHolder", "JOHN DOE");
                creditCardParams.put("expiryDate", "12/28");
                creditCardParams.put("cvv", "123");
                selectedStrategy = PaymentStrategyFactory.getStrategy(
                    "CREDIT_CARD", creditCardParams);
            }
        }
        
        if (selectedStrategy != null) {
            context.setPaymentStrategy(selectedStrategy);
            PaymentResult result = context.executePayment();
            printResult(result);
        } else {
            System.out.println("没有找到合适的支付策略");
        }
    }
    
    private static void printResult(PaymentResult result) {
        System.out.println("\n支付结果:");
        System.out.println("成功: " + result.isSuccess());
        System.out.println("交易号: " + result.getTransactionId());
        System.out.println("消息: " + result.getMessage());
        System.out.println("时间: " + result.getPayTime());
        if (result.getActualAmount() != null) {
            System.out.println("实际金额: " + result.getActualAmount());
        }
    }
}

四、高级应用:策略模式组合模式

java
java
下载
复制
// 复合策略:组合多个策略形成策略链
public class CompositePaymentStrategy implements PaymentStrategy {
    private final List<PaymentStrategy> strategies;
    private final CompositeStrategyMode mode;
    
    public enum CompositeStrategyMode {
        FALLBACK,      // 降级模式:按顺序尝试,直到成功
        SPLIT,         // 拆分模式:金额拆分到多个策略
        PARALLEL       // 并行模式:同时尝试多个策略
    }
    
    public CompositePaymentStrategy(List<PaymentStrategy> strategies, 
                                   CompositeStrategyMode mode) {
        this.strategies = new ArrayList<>(strategies);
        this.mode = mode;
    }
    
    @Override
    public PaymentResult pay(BigDecimal amount) {
        switch (mode) {
            case FALLBACK:
                return executeFallback(amount);
            case SPLIT:
                return executeSplit(amount);
            case PARALLEL:
                return executeParallel(amount);
            default:
                throw new IllegalStateException("未知的组合策略模式: " + mode);
        }
    }
    
    private PaymentResult executeFallback(BigDecimal amount) {
        for (PaymentStrategy strategy : strategies) {
            if (!strategy.isSupported()) {
                continue;
            }
            
            System.out.println("尝试策略: " + strategy.getStrategyName());
            PaymentResult result = strategy.pay(amount);
            
            if (result.isSuccess()) {
                return PaymentResult.builder()
                    .success(true)
                    .transactionId(result.getTransactionId())
                    .message("组合支付成功(降级模式),最终策略: " + 
                            strategy.getStrategyName())
                    .actualAmount(amount)
                    .build();
            }
        }
        
        return PaymentResult.builder()
            .success(false)
            .message("所有降级策略都失败")
            .build();
    }
    
    private PaymentResult executeSplit(BigDecimal amount) {
        if (strategies.isEmpty()) {
            throw new IllegalStateException("拆分支付至少需要一个策略");
        }
        
        // 将金额平均拆分
        BigDecimal splitAmount = amount.divide(
            new BigDecimal(strategies.size()), 2, RoundingMode.HALF_UP);
        
        List<PaymentResult> results = new ArrayList<>();
        int successCount = 0;
        
        for (int i = 0; i < strategies.size(); i++) {
            PaymentStrategy strategy = strategies.get(i);
            BigDecimal currentAmount = (i == strategies.size() - 1) ? 
                amount.subtract(splitAmount.multiply(new BigDecimal(strategies.size() - 1))) : 
                splitAmount;
            
            System.out.println("策略" + (i+1) + "(" + strategy.getStrategyName() + 
                             ")支付金额: " + currentAmount);
            
            PaymentResult result = strategy.pay(currentAmount);
            results.add(result);
            
            if (result.isSuccess()) {
                successCount++;
            } else {
                // 如果有任何一个失败,尝试回滚成功的
                rollbackSuccessfulPayments(results, i);
                return PaymentResult.builder()
                    .success(false)
                    .message("拆分支付失败,策略" + strategy.getStrategyName() + 
                            "支付失败: " + result.getMessage())
                    .build();
            }
        }
        
        return PaymentResult.builder()
            .success(true)
            .transactionId("SPLIT_" + System.currentTimeMillis())
            .message("拆分支付成功,使用了" + successCount + "个策略")
            .actualAmount(amount)
            .build();
    }
    
    private PaymentResult executeParallel(BigDecimal amount) {
        // 简化实现:实际需要处理线程安全
        ExecutorService executor = Executors.newFixedThreadPool(strategies.size());
        List<Future<PaymentResult>> futures = new ArrayList<>();
        
        for (PaymentStrategy strategy : strategies) {
            Callable<PaymentResult> task = () -> strategy.pay(amount);
            futures.add(executor.submit(task));
        }
        
        executor.shutdown();
        
        try {
            // 等待第一个成功的
            for (Future<PaymentResult> future : futures) {
                try {
                    PaymentResult result = future.get(10, TimeUnit.SECONDS);
                    if (result.isSuccess()) {
                        // 取消其他任务
                        for (Future<PaymentResult> f : futures) {
                            if (!f.isDone()) {
                                f.cancel(true);
                            }
                        }
                        return result;
                    }
                } catch (Exception e) {
                    // 继续尝试下一个
                }
            }
        } catch (Exception e) {
            Thread.currentThread().interrupt();
        }
        
        return PaymentResult.builder()
            .success(false)
            .message("并行支付全部失败")
            .build();
    }
    
    private void rollbackSuccessfulPayments(List<PaymentResult> results, int currentIndex) {
        // 实现回滚逻辑
        for (int i = 0; i < currentIndex; i++) {
            PaymentResult result = results.get(i);
            if (result.isSuccess()) {
                System.out.println("回滚策略" + (i+1) + "的支付: " + 
                                 result.getTransactionId());
                // 实际回滚逻辑...
            }
        }
    }
    
    @Override
    public String getStrategyName() {
        return "COMPOSITE_" + mode;
    }
    
    @Override
    public boolean isSupported() {
        return strategies.stream().anyMatch(PaymentStrategy::isSupported);
    }
}

五、应用场景深度分析

5.1 支付系统(如前所示)

5.2 排序算法策略

java
java
下载
复制
// 排序策略接口
public interface SortStrategy<T extends Comparable<T>> {
    List<T> sort(List<T> items);
    String getName();
    SortPerformance analyzePerformance(List<T> items);
}

// 性能分析类
class SortPerformance {
    private final long timeMillis;
    private final long memoryUsed;
    private final int comparisons;
    
    public SortPerformance(long timeMillis, long memoryUsed, int comparisons) {
        this.timeMillis = timeMillis;
        this.memoryUsed = memoryUsed;
        this.comparisons = comparisons;
    }
    
    // getters...
}

// 具体排序策略
public class QuickSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
    @Override
    public List<T> sort(List<T> items) {
        List<T> sorted = new ArrayList<>(items);
        quickSort(sorted, 0, sorted.size() - 1);
        return sorted;
    }
    
    private void quickSort(List<T> items, int low, int high) {
        if (low < high) {
            int pi = partition(items, low, high);
            quickSort(items, low, pi - 1);
            quickSort(items, pi + 1, high);
        }
    }
    
    private int partition(List<T> items, int low, int high) {
        T pivot = items.get(high);
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            if (items.get(j).compareTo(pivot) <= 0) {
                i++;
                Collections.swap(items, i, j);
            }
        }
        Collections.swap(items, i + 1, high);
        return i + 1;
    }
    
    @Override
    public String getName() {
        return "快速排序";
    }
    
    @Override
    public SortPerformance analyzePerformance(List<T> items) {
        long startTime = System.nanoTime();
        long startMemory = Runtime.getRuntime().totalMemory() - 
                          Runtime.getRuntime().freeMemory();
        
        List<T> sorted = sort(items);
        
        long endTime = System.nanoTime();
        long endMemory = Runtime.getRuntime().totalMemory() - 
                        Runtime.getRuntime().freeMemory();
        
        return new SortPerformance(
            (endTime - startTime) / 1_000_000,
            endMemory - startMemory,
            estimateComparisons(items.size())
        );
    }
    
    private int estimateComparisons(int n) {
        return (int) (n * Math.log(n) / Math.log(2));
    }
}

// 排序上下文
public class SortContext<T extends Comparable<T>> {
    private SortStrategy<T> strategy;
    private List<T> items;
    
    public SortContext(List<T> items) {
        this.items = new ArrayList<>(items);
    }
    
    public void setStrategy(SortStrategy<T> strategy) {
        this.strategy = strategy;
    }
    
    public List<T> executeSort() {
        if (strategy == null) {
            throw new IllegalStateException("请先设置排序策略");
        }
        return strategy.sort(items);
    }
    
    public SortPerformance analyze() {
        if (strategy == null) {
            throw new IllegalStateException("请先设置排序策略");
        }
        return strategy.analyzePerformance(items);
    }
}

5.3 压缩算法策略

java
java
下载
复制
public interface CompressionStrategy {
    byte[] compress(byte[] data) throws IOException;
    byte[] decompress(byte[] compressedData) throws IOException;
    String getAlgorithmName();
    double getCompressionRatio(byte[] original, byte[] compressed);
}

// GZIP压缩策略
public class GzipCompressionStrategy implements CompressionStrategy {
    @Override
    public byte[] compress(byte[] data) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
            gzip.write(data);
        }
        return bos.toByteArray();
    }
    
    @Override
    public byte[] decompress(byte[] compressedData) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try (GZIPInputStream gzip = new GZIPInputStream(
                new ByteArrayInputStream(compressedData))) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzip.read(buffer)) > 0) {
                bos.write(buffer, 0, len);
            }
        }
        return bos.toByteArray();
    }
    
    @Override
    public String getAlgorithmName() {
        return "GZIP";
    }
    
    @Override
    public double getCompressionRatio(byte[] original, byte[] compressed) {
        return (double) compressed.length / original.length;
    }
}

// 压缩管理器
public class CompressionManager {
    private CompressionStrategy strategy;
    
    public void setStrategy(CompressionStrategy strategy) {
        this.strategy = strategy;
    }
    
    public CompressionResult compress(byte[] data) throws IOException {
        long startTime = System.currentTimeMillis();
        byte[] compressed = strategy.compress(data);
        long endTime = System.currentTimeMillis();
        
        double ratio = strategy.getCompressionRatio(data, compressed);
        
        return new CompressionResult(
            compressed,
            ratio,
            endTime - startTime,
            data.length,
            compressed.length
        );
    }
}

5.4 验证策略

java
java
下载
复制
public interface ValidationStrategy {
    boolean validate(String input);
    String getErrorMessage();
    ValidationRule getRule();
}

public class EmailValidationStrategy implements ValidationStrategy {
    private static final Pattern EMAIL_PATTERN = 
        Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
    
    @Override
    public boolean validate(String input) {
        if (input == null) return false;
        return EMAIL_PATTERN.matcher(input).matches();
    }
    
    @Override
    public String getErrorMessage() {
        return "邮箱格式不正确";
    }
    
    @Override
    public ValidationRule getRule() {
        return ValidationRule.EMAIL;
    }
}

// 验证上下文
public class Validator {
    private List<ValidationStrategy> strategies = new ArrayList<>();
    
    public void addStrategy(ValidationStrategy strategy) {
        strategies.add(strategy);
    }
    
    public ValidationResult validate(String input) {
        List<String> errors = new ArrayList<>();
        
        for (ValidationStrategy strategy : strategies) {
            if (!strategy.validate(input)) {
                errors.add(strategy.getErrorMessage());
            }
        }
        
        return new ValidationResult(
            errors.isEmpty(),
            errors,
            input
        );
    }
}

六、优缺点深度解析

6.1 优点分析

6.1.1 开闭原则支持

java
java
下载
复制
// 易于扩展新策略
public class NewPaymentStrategy implements PaymentStrategy {
    // 新增支付方式,无需修改现有代码
    @Override
    public PaymentResult pay(BigDecimal amount) {
        // 新支付方式实现
        return null;
    }
    
    @Override
    public String getStrategyName() {
        return "NEW_PAYMENT";
    }
    
    @Override
    public boolean isSupported() {
        return true;
    }
}

6.1.2 消除条件语句

java
java
下载
复制
// 传统if-else方式(不推荐)
public class BadPaymentProcessor {
    public PaymentResult process(String paymentType, BigDecimal amount) {
        if ("CREDIT_CARD".equals(paymentType)) {
            // 信用卡处理逻辑
        } else if ("PAYPAL".equals(paymentType)) {
            // PayPal处理逻辑
        } else if ("ALIPAY".equals(paymentType)) {
            // 支付宝处理逻辑
        } else if ("WECHAT_PAY".equals(paymentType)) {
            // 微信支付处理逻辑
        }
        // 每增加一种支付方式就要修改这里
        return null;
    }
}

// 策略模式方式(推荐)
public class GoodPaymentProcessor {
    private PaymentStrategy strategy;
    
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public PaymentResult process(BigDecimal amount) {
        return strategy.pay(amount);
    }
}

6.1.3 算法复用

java
java
下载
复制
// 多个上下文可以共享相同策略
public class StrategyReuseDemo {
    public static void main(String[] args) {
        PaymentStrategy wechatPay = new WeChatPaymentStrategy("openId123");
        
        // 订单1使用微信支付
        PaymentContext order1 = new PaymentContext("ORDER001", 
            new BigDecimal("100.00"));
        order1.setPaymentStrategy(wechatPay);
        
        // 订单2也使用微信支付
        PaymentContext order2 = new PaymentContext("ORDER002", 
            new BigDecimal("200.00"));
        order2.setPaymentStrategy(wechatPay); // 复用同一个策略实例
        
        // 可以配置不同的策略参数
        PaymentStrategy alipay1 = new AlipayPaymentStrategy("account1");
        PaymentStrategy alipay2 = new AlipayPaymentStrategy("account2");
    }
}

6.2 缺点分析

6.2.1 策略类数量爆炸

java
java
下载
复制
// 当策略变多时,管理困难
// 策略1
public class CreditCardStrategy implements PaymentStrategy { /* ... */ }
// 策略2
public class PayPalStrategy implements PaymentStrategy { /* ... */ }
// 策略3
public class AlipayStrategy implements PaymentStrategy { /* ... */ }
// 策略4
public class WeChatPayStrategy implements PaymentStrategy { /* ... */ }
// 策略5
public class ApplePayStrategy implements PaymentStrategy { /* ... */ }
// 策略6
public class GooglePayStrategy implements PaymentStrategy { /* ... */ }
// 策略7
public class BankTransferStrategy implements PaymentStrategy { /* ... */ }
// 策略8
public class CryptocurrencyStrategy implements PaymentStrategy { /* ... */ }
// ... 更多策略

解决方案:使用策略工厂和配置文件管理

java
java
下载
复制
@Configuration
public class PaymentStrategyConfig {
    
    @Bean
    @ConditionalOnProperty(name = "payment.strategy.credit-card.enabled", 
                          havingValue = "true")
    public PaymentStrategy creditCardStrategy() {
        return new CreditCardStrategy();
    }
    
    @Bean
    @ConditionalOnProperty(name = "payment.strategy.paypal.enabled", 
                          havingValue = "true")
    public PaymentStrategy paypalStrategy() {
        return new PayPalStrategy();
    }
    
    // 通过配置文件控制哪些策略启用
}

6.2.2 客户端必须了解所有策略

java
java
下载
复制
// 客户端需要知道所有策略
public class BadClient {
    public void processPayment(String type) {
        PaymentStrategy strategy;
        switch (type) {
            case "credit-card":
                strategy = new CreditCardStrategy("4111...");
                break;
            case "paypal":
                strategy = new PayPalStrategy("email", "pwd");
                break;
            case "alipay":
                strategy = new AlipayStrategy("account");
                break;
            // 新增策略需要修改这里
            default:
                throw new IllegalArgumentException("Unknown type");
        }
        // ...
    }
}

解决方案:使用策略注册表

java
java
下载
复制
public class StrategyRegistry {
    private final Map<String, Supplier<PaymentStrategy>> registry = new HashMap<>();
    
    public void register(String type, Supplier<PaymentStrategy> supplier) {
        registry.put(type, supplier);
    }
    
    public PaymentStrategy getStrategy(String type, Object... params) {
        Supplier<PaymentStrategy> supplier = registry.get(type);
        if (supplier == null) {
            throw new IllegalArgumentException("未注册的策略类型: " + type);
        }
        return supplier.get();
    }
}

6.2.3 性能开销

java
java
下载
复制
public class StrategyPerformanceTest {
    
    @Test
    public void testPerformance() {
        int iterations = 1000000;
        
        // 直接调用
        long directStart = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            doDirectPayment();
        }
        long directTime = System.nanoTime() - directStart;
        
        // 策略模式调用
        long strategyStart = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            doStrategyPayment();
        }
        long strategyTime = System.nanoTime() - strategyStart;
        
        System.out.println("直接调用: " + directTime + "ns");
        System.out.println("策略调用: " + strategyTime + "ns");
        System.out.println("开销比例: " + 
                          (double)(strategyTime - directTime) / directTime * 100 + "%");
    }
}

七、使用要点与最佳实践

7.1 策略选择指南

场景推荐方案理由
算法经常变化策略模式易于扩展和修改算法
需要消除条件语句策略模式用多态替代条件判断
多种算法变体策略模式封装算法家族
算法需要重用策略模式策略可在不同上下文重用
简单条件判断简单if-else避免过度设计
算法很少变化模板方法模式使用继承更简单

7.2 策略模式与相关模式对比

7.2.1 策略模式 vs 工厂模式

java
java
下载
复制
// 工厂模式:创建对象
public class PaymentFactory {
    public static Payment createPayment(String type) {
        switch (type) {
            case "CREDIT_CARD": return new CreditCardPayment();
            case "PAYPAL": return new PayPalPayment();
            default: throw new IllegalArgumentException();
        }
    }
}

// 策略模式:选择算法
public class PaymentContext {
    private PaymentStrategy strategy;
    
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;  // 设置算法
    }
    
    public void execute() {
        strategy.pay();  // 执行算法
    }
}

7.2.2 策略模式 vs 状态模式

java
java
下载
复制
// 状态模式:状态改变时自动切换行为
public class OrderState {
    private State currentState;
    
    public void setState(State state) {
        this.currentState = state;
    }
    
    public void process() {
        currentState.handle();  // 行为由状态决定
        // 状态可能自动转换
    }
}

// 策略模式:手动选择算法
public class Sorter {
    private SortStrategy strategy;
    
    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;  // 手动设置策略
    }
    
    public void sort() {
        strategy.sort();  // 执行选择的算法
    }
}

7.3 性能优化技巧

7.3.1 策略对象缓存

java
java
下载
复制
public class StrategyCache {
    private final Map<String, PaymentStrategy> cache = new ConcurrentHashMap<>();
    private final Map<String, Long> creationTime = new ConcurrentHashMap<>();
    private static final long CACHE_TIMEOUT = 30 * 60 * 1000; // 30分钟
    
    public PaymentStrategy getOrCreate(String type, Map<String, Object> params) {
        String cacheKey = buildCacheKey(type, params);
        
        // 检查缓存
        PaymentStrategy cached = cache.get(cacheKey);
        if (cached != null && !isExpired(cacheKey)) {
            return cached;
        }
        
        // 创建新策略
        PaymentStrategy strategy = createStrategy(type, params);
        cache.put(cacheKey, strategy);
        creationTime.put(cacheKey, System.currentTimeMillis());
        
        return strategy;
    }
    
    private boolean isExpired(String cacheKey) {
        Long time = creationTime.get(cacheKey);
        if (time == null) return true;
        return System.currentTimeMillis() - time > CACHE_TIMEOUT;
    }
    
    // 清理过期缓存
    public void cleanup() {
        long now = System.currentTimeMillis();
        cache.entrySet().removeIf(entry -> 
            now - creationTime.getOrDefault(entry.getKey(), 0L) > CACHE_TIMEOUT
        );
    }
}

7.3.2 延迟初始化策略

java
java
下载
复制
public class LazyStrategy<T extends PaymentStrategy> {
    private final Supplier<T> strategySupplier;
    private volatile T strategy;
    
    public LazyStrategy(Supplier<T> supplier) {
        this.strategySupplier = supplier;
    }
    
    public T get() {
        if (strategy == null) {
            synchronized (this) {
                if (strategy == null) {
                    strategy = strategySupplier.get();
                }
            }
        }
        return strategy;
    }
}

// 使用示例
public class PaymentService {
    private final LazyStrategy<CreditCardStrategy> creditCardStrategy =
        new LazyStrategy<>(() -> new CreditCardStrategy("card-number"));
    
    public void process() {
        PaymentStrategy strategy = creditCardStrategy.get(); // 延迟初始化
        // ...
    }
}

7.4 测试策略

java
java
下载
复制
public class StrategyPatternTest {
    
    @Test
    public void testCreditCardStrategy() {
        // 准备
        PaymentStrategy strategy = new CreditCardPaymentStrategy(
            "4111111111111111", "TEST USER", "12/30", "123");
        PaymentContext context = new PaymentContext("TEST_ORDER", 
            new BigDecimal("100.00"));
        context.setPaymentStrategy(strategy);
        
        // 执行
        PaymentResult result = context.executePayment();
        
        // 验证
        assertNotNull(result);
        assertEquals(PaymentContext.PaymentContextState.SUCCESS, 
                    context.getState());
    }
    
    @Test
    public void testStrategySwitching() {
        // 测试策略切换
        PaymentContext context = new PaymentContext("SWITCH_ORDER", 
            new BigDecimal("200.00"));
        
        // 使用信用卡
        PaymentStrategy creditCard = new CreditCardPaymentStrategy(
            "4111111111111111", "USER", "12/30", "123");
        context.setPaymentStrategy(creditCard);
        PaymentResult result1 = context.executePayment();
        
        // 切换到PayPal
        PaymentStrategy paypal = new PayPalPaymentStrategy(
            "test@example.com", "password");
        context.setPaymentStrategy(paypal);
        PaymentResult result2 = context.executePayment();
        
        // 验证两次支付使用不同策略
        assertNotEquals(result1.getTransactionId(), result2.getTransactionId());
    }
    
    @Test
    public void testStrategyFactory() {
        // 测试工厂创建策略
        Map<String, Object> params = new HashMap<>();
        params.put("walletAddress", "0x123...");
        
        PaymentStrategy strategy = PaymentStrategyFactory.getStrategy(
            "CRYPTO_ETH", params);
        
        assertNotNull(strategy);
        assertTrue(strategy instanceof CryptocurrencyPaymentStrategy);
    }
}

八、在Spring框架中的实践

8.1 Spring中的策略模式

java
java
下载
复制
// 1. 定义策略接口
public interface NotificationStrategy {
    void sendNotification(String message, String recipient);
    boolean supports(NotificationType type);
}

// 2. 具体策略实现
@Component
@Order(1)
public class EmailNotificationStrategy implements NotificationStrategy {
    
    @Autowired
    private JavaMailSender mailSender;
    
    @Value("${notification.email.from}")
    private String fromEmail;
    
    @Override
    public void sendNotification(String message, String recipient) {
        SimpleMailMessage email = new SimpleMailMessage();
        email.setFrom(fromEmail);
        email.setTo(recipient);
        email.setSubject("系统通知");
        email.setText(message);
        
        mailSender.send(email);
    }
    
    @Override
    public boolean supports(NotificationType type) {
        return NotificationType.EMAIL == type;
    }
}

@Component
@Order(2)
public class SmsNotificationStrategy implements NotificationStrategy {
    
    @Autowired
    private SmsService smsService;
    
    @Override
    public void sendNotification(String message, String recipient) {
        smsService.sendSms(recipient, message);
    }
    
    @Override
    public boolean supports(NotificationType type) {
        return NotificationType.SMS == type;
    }
}

// 3. 策略工厂(使用Spring依赖注入)
@Component
public class NotificationStrategyFactory {
    
    private final List<NotificationStrategy> strategies;
    
    @Autowired
    public NotificationStrategyFactory(List<NotificationStrategy> strategies) {
        this.strategies = strategies;
    }
    
    public NotificationStrategy getStrategy(NotificationType type) {
        return strategies.stream()
            .filter(strategy -> strategy.supports(type))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException(
                "不支持的通知类型: " + type));
    }
}

// 4. 使用策略的服务
@Service
public class NotificationService {
    
    @Autowired
    private NotificationStrategyFactory strategyFactory;
    
    public void sendNotification(NotificationRequest request) {
        NotificationStrategy strategy = strategyFactory.getStrategy(
            request.getType());
        
        strategy.sendNotification(
            request.getMessage(),
            request.getRecipient()
        );
        
        // 记录日志
        logNotification(request, strategy.getClass().getSimpleName());
    }
    
    private void logNotification(NotificationRequest request, String strategyName) {
        // 记录发送日志
    }
}

// 5. 配置类
@Configuration
public class NotificationConfig {
    
    @Bean
    @ConditionalOnProperty(name = "notification.email.enabled", 
                          havingValue = "true")
    public NotificationStrategy emailNotificationStrategy() {
        return new EmailNotificationStrategy();
    }
    
    @Bean
    @ConditionalOnProperty(name = "notification.sms.enabled", 
                          havingValue = "true")
    public NotificationStrategy smsNotificationStrategy() {
        return new SmsNotificationStrategy();
    }
}

8.2 Spring Boot自动配置策略

java
java
下载
复制
// 自动配置策略
@Configuration
@EnableConfigurationProperties(PaymentProperties.class)
public class PaymentAutoConfiguration {
    
    @Bean
    @ConditionalOnClass(name = "com.alipay.api.AlipayClient")
    @ConditionalOnProperty(prefix = "payment.alipay", name = "enabled")
    public PaymentStrategy alipayStrategy(PaymentProperties properties) {
        return new AlipayPaymentStrategy(
            properties.getAlipay().getAppId(),
            properties.getAlipay().getPrivateKey(),
            properties.getAlipay().getPublicKey()
        );
    }
    
    @Bean
    @ConditionalOnBean(PaymentStrategy.class)
    public PaymentStrategyRegistry paymentStrategyRegistry(
            List<PaymentStrategy> strategies) {
        return new PaymentStrategyRegistry(strategies);
    }
}

// 配置属性
@ConfigurationProperties(prefix = "payment")
@Data
public class PaymentProperties {
    private Alipay alipay = new Alipay();
    private WechatPay wechatPay = new WechatPay();
    
    @Data
    public static class Alipay {
        private boolean enabled = false;
        private String appId;
        private String privateKey;
        private String publicKey;
    }
    
    @Data
    public static class WechatPay {
        private boolean enabled = false;
        private String appId;
        private String mchId;
        private String apiKey;
    }
}

九、实际项目中的最佳实践

9.1 微服务架构中的策略模式

java
java
下载
复制
// 服务发现策略
public interface ServiceDiscoveryStrategy {
    List<ServiceInstance> discover(String serviceName);
    void register(ServiceInstance instance);
    void deregister(ServiceInstance instance);
}

// 具体实现
@Component
@Profile("consul")
public class ConsulDiscoveryStrategy implements ServiceDiscoveryStrategy {
    
    @Autowired
    private ConsulClient consulClient;
    
    @Override
    public List<ServiceInstance> discover(String serviceName) {
        // 从Consul发现服务
        return consulClient.getHealthServices(serviceName, true, null)
            .getValue()
            .stream()
            .map(this::toServiceInstance)
            .collect(Collectors.toList());
    }
    
    private ServiceInstance toServiceInstance(HealthService healthService) {
        // 转换逻辑
        return new ServiceInstance(
            healthService.getService().getId(),
            healthService.getService().getService(),
            healthService.getService().getAddress(),
            healthService.getService().getPort()
        );
    }
}

@Component
@Profile("nacos")
public class NacosDiscoveryStrategy implements ServiceDiscoveryStrategy {
    
    @Autowired
    private NamingService namingService;
    
    @Override
    public List<ServiceInstance> discover(String serviceName) {
        // 从Nacos发现服务
        return namingService.getAllInstances(serviceName)
            .stream()
            .map(this::toServiceInstance)
            .collect(Collectors.toList());
    }
}

// 服务调用策略
public interface LoadBalanceStrategy {
    ServiceInstance select(List<ServiceInstance> instances);
    String getStrategyName();
}

@Component
@Qualifier("randomLoadBalance")
public class RandomLoadBalanceStrategy implements LoadBalanceStrategy {
    
    private final Random random = new Random();
    
    @Override
    public ServiceInstance select(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            throw new IllegalStateException("没有可用服务实例");
        }
        return instances.get(random.nextInt(instances.size()));
    }
    
    @Override
    public String getStrategyName() {
        return "RANDOM";
    }
}

@Component
@Qualifier("roundRobinLoadBalance")
public class RoundRobinLoadBalanceStrategy implements LoadBalanceStrategy {
    
    private final AtomicInteger counter = new AtomicInteger(0);
    
    @Override
    public ServiceInstance select(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            throw new IllegalStateException("没有可用服务实例");
        }
        int index = Math.abs(counter.getAndIncrement() % instances.size());
        return instances.get(index);
    }
    
    @Override
    public String getStrategyName() {
        return "ROUND_ROBIN";
    }
}

9.2 配置中心管理策略

yaml
yaml
复制
# application.yml
strategy:
  payment:
    enabled-strategies: 
      - credit-card
      - alipay
      - wechat-pay
    default-strategy: alipay
    credit-card:
      enabled: true
      priority: 1
      config:
        support-3d-secure: true
    alipay:
      enabled: true
      priority: 2
      config:
        sandbox: false
    wechat-pay:
      enabled: true
      priority: 3
      config:
        app-id: wx1234567890

9.3 监控和指标收集

java
java
下载
复制
// 策略执行监控
@Aspect
@Component
@Slf4j
public class StrategyExecutionMonitor {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @Around("@within(org.springframework.stereotype.Component) && " +
           "execution(* com.example..*Strategy+.*(..))")
    public Object monitorStrategyExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String strategyName = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        Timer.Sample sample = Timer.start(meterRegistry);
        Counter successCounter = meterRegistry.counter(
            "strategy.execution", 
            "strategy", strategyName,
            "method", methodName,
            "status", "success"
        );
        Counter failureCounter = meterRegistry.counter(
            "strategy.execution",
            "strategy", strategyName,
            "method", methodName,
            "status", "failure"
        );
        
        try {
            Object result = joinPoint.proceed();
            sample.stop(Timer.builder("strategy.execution.time")
                .description("策略执行时间")
                .tags("strategy", strategyName, "method", methodName)
                .register(meterRegistry));
            successCounter.increment();
            return result;
        } catch (Exception e) {
            failureCounter.increment();
            throw e;
        }
    }
}

十、总结与选择建议

10.1 策略模式使用时机

场景推荐使用说明
多种算法变体✅ 推荐需要封装不同的算法实现
消除条件语句✅ 推荐用多态替代复杂if-else
算法需要独立测试✅ 推荐策略可以单独单元测试
算法需要动态切换✅ 推荐运行时切换策略
简单算法选择⚠️ 谨慎过度设计风险
算法极少变化❌ 不推荐增加不必要的复杂度

10.2 性能与复杂度平衡

java
java
下载
复制
// 性能敏感场景的优化
public class OptimizedStrategyContext {
    
    // 使用枚举代替字符串匹配
    public enum StrategyType {
        FAST(new FastStrategy()),
        MEMORY_EFFICIENT(new MemoryEfficientStrategy()),
        BALANCED(new BalancedStrategy());
        
        private final Strategy strategy;
        
        StrategyType(Strategy strategy) {
            this.strategy = strategy;
        }
        
        public Strategy getStrategy() {
            return strategy;
        }
    }
    
    // 使用数组替代Map,提高性能
    private static final Strategy[] STRATEGY_CACHE = new Strategy[StrategyType.values().length];
    
    static {
        for (StrategyType type : StrategyType.values()) {
            STRATEGY_CACHE[type.ordinal()] = type.getStrategy();
        }
    }
    
    public Strategy getStrategy(StrategyType type) {
        return STRATEGY_CACHE[type.ordinal()];
    }
}

10.3 企业级最佳实践总结

  1. 策略注册机制:使用工厂模式管理策略创建
  2. 配置驱动:通过配置文件启用/禁用策略
  3. 监控告警:为策略执行添加监控指标
  4. 熔断降级:为策略调用添加熔断机制
  5. 版本管理:支持策略的版本和灰度发布
  6. 文档完善:为每个策略提供详细文档
  7. 测试覆盖:确保每个策略都有充分的单元测试
  8. 性能基准:建立策略性能基准测试

10.4 代码质量检查规则

java
java
下载
复制
// 自定义Checkstyle规则示例
public class StrategyPatternRules {
    // 规则1: 策略接口必须有明确的命名
    // 推荐: *Strategy,如PaymentStrategy、SortStrategy
    // 不推荐: *Service、*Handler(除非明确是策略)
    
    // 规则2: 策略类应该是无状态的
    // 如果需要有状态,考虑使用上下文传递状态
    
    // 规则3: 避免策略类之间的耦合
    // 策略之间应该独立,不互相依赖
    
    // 规则4: 策略接口应该保持精简
    // 接口方法不宜过多,遵循接口隔离原则
    
    // 规则5: 为策略添加合适的日志
    // 记录策略选择和执行情况
}

策略模式是实际项目中最常用的设计模式之一,正确使用可以显著提高代码的可维护性和扩展性。关键在于识别出系统中变化的算法部分,并将其封装为策略,同时确保策略接口的设计足够通用,能够适应未来的变化需求。