← 返回首页
🧩

策略模式:运行时算法切换与可扩展设计

📂 architecture ⏱ 2 min 384 words

策略模式:运行时算法切换与可扩展设计

策略模式核心思想

策略模式定义一系列算法,将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端,是实现开闭原则(OCP)的经典方式。在架构中,策略模式广泛用于支付方式、路由规则、缓存策略、压缩算法等场景。

// 策略接口
public interface PricingStrategy {
    BigDecimal calculatePrice(Order order);
    String getStrategyName();
}

// 策略实现
public class RegularPricingStrategy implements PricingStrategy {
    public BigDecimal calculatePrice(Order order) {
        return order.getOriginalPrice();
    }
    public String getStrategyName() { return "REGULAR"; }
}

public class VIPPricingStrategy implements PricingStrategy {
    private final BigDecimal discount;
    
    public VIPPricingStrategy(BigDecimal discount) {
        this.discount = discount;
    }
    
    public BigDecimal calculatePrice(Order order) {
        return order.getOriginalPrice().multiply(BigDecimal.ONE.subtract(discount));
    }
    public String getStrategyName() { return "VIP"; }
}

// 策略上下文
public class PricingContext {
    private final Map<String, PricingStrategy> strategies;
    
    public PricingContext(List<PricingStrategy> strategyList) {
        this.strategies = strategyList.stream()
            .collect(Collectors.toMap(PricingStrategy::getStrategyName, s -> s));
    }
    
    public BigDecimal calculate(String strategyName, Order order) {
        PricingStrategy strategy = strategies.get(strategyName);
        if (strategy == null) {
            throw new IllegalArgumentException("Unknown strategy: " + strategyName);
        }
        return strategy.calculatePrice(order);
    }
}

支付策略模式实现

支付系统是策略模式的经典应用场景,不同支付方式封装为独立策略,运行时根据用户选择动态切换。

interface PaymentStrategy {
  pay(amount: number): Promise<PaymentResult>;
  refund(transactionId: string, amount: number): Promise<RefundResult>;
  getName(): string;
}

class WechatPayStrategy implements PaymentStrategy {
  constructor(private config: WechatPayConfig) {}
  
  async pay(amount: number): Promise<PaymentResult> {
    const params = {
      appid: this.config.appId,
      mch_id: this.config.mchId,
      total_fee: Math.round(amount * 100),
      nonce_str: generateNonceStr(),
    };
    const sign = this.generateSign(params);
    // 调用微信支付API
    return await this.wechatClient.unifiedOrder({ ...params, sign });
  }
  
  async refund(transactionId: string, amount: number): Promise<RefundResult> {
    return await this.wechatClient.refund({
      transaction_id: transactionId,
      refund_fee: Math.round(amount * 100),
    });
  }
  
  getName(): string { return 'WECHAT'; }
}

class AlipayStrategy implements PaymentStrategy {
  constructor(private config: AlipayConfig) {}
  
  async pay(amount: number): Promise<PaymentResult> {
    const bizContent = {
      total_amount: amount.toFixed(2),
      subject: '商品支付',
      product_code: 'FAST_INSTANT_TRADE_PAY',
    };
    return await this.alipayClient.pagePay(bizContent);
  }
  
  async refund(transactionId: string, amount: number): Promise<RefundResult> {
    return await this.alipayClient.refund({
      trade_no: transactionId,
      refund_amount: amount.toFixed(2),
    });
  }
  
  getName(): string { return 'ALIPAY'; }
}

// 策略工厂
class PaymentStrategyFactory {
  private strategies = new Map<string, PaymentStrategy>();
  
  register(strategy: PaymentStrategy): void {
    this.strategies.set(strategy.getName(), strategy);
  }
  
  getStrategy(name: string): PaymentStrategy {
    const strategy = this.strategies.get(name);
    if (!strategy) throw new Error(`Payment strategy ${name} not found`);
    return strategy;
  }
}

路由策略与算法切换

微服务路由、负载均衡、数据分片等场景都适合使用策略模式实现可扩展的算法切换。

// 负载均衡策略
type LoadBalanceStrategy interface {
    Select(instances []ServiceInstance) ServiceInstance
}

type RoundRobinStrategy struct {
    counter uint64
}

func (r *RoundRobinStrategy) Select(instances []ServiceInstance) ServiceInstance {
    idx := atomic.AddUint64(&r.counter, 1) % uint64(len(instances))
    return instances[idx]
}

type WeightedRandomStrategy struct{}

func (w *WeightedRandomStrategy) Select(instances []ServiceInstance) ServiceInstance {
    totalWeight := 0
    for _, inst := range instances {
        totalWeight += inst.Weight
    }
    rand := rand.Intn(totalWeight)
    for _, inst := range instances {
        rand -= inst.Weight
        if rand < 0 {
            return inst
        }
    }
    return instances[0]
}

策略模式最佳实践

策略模式通过消除条件分支提升代码可维护性,支持新策略的无侵入添加。配合工厂模式或依赖注入实现策略的动态注册和选择。注意策略数量膨胀问题,当策略超过一定数量时考虑引入规则引擎。