策略模式:运行时算法切换与可扩展设计
策略模式:运行时算法切换与可扩展设计
策略模式核心思想
策略模式定义一系列算法,将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端,是实现开闭原则(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]
}
策略模式最佳实践
策略模式通过消除条件分支提升代码可维护性,支持新策略的无侵入添加。配合工厂模式或依赖注入实现策略的动态注册和选择。注意策略数量膨胀问题,当策略超过一定数量时考虑引入规则引擎。