Skip to content

策略模式

什么是策略模式?

策略模式(Strategy Pattern)是一种定义一系列算法的方法。从概念上看,这些算法完成的功能相同,但实现各不相同。通过将不同算法分别封装到独立的类中,并通过“策略上下文(Context)”根据运行时需求动态地选择合适的“策略类”来实现相同的功能。

举个简单例子:假设我们有一个支付系统,支持多种支付方式(支付宝、微信支付、信用卡支付等)。使用策略模式,我们可以把每种具体支付算法打包在单独的策略类中,统一对外提供支付接口,以便随时切换。

策略模式的实现原理

  • 策略接口(Strategy Interface):定义了算法的统一方法或接口。
  • 具体策略(Concrete Strategy):实现策略接口的不同算法类。
  • 上下文(Context):维护对某个策略对象的引用,并在合适的时机调用策略方法。

通过将不同策略独立封装,上下文可以在无需更改原有代码的情况下,灵活地组合和切换策略。

核心实现

下面以 TypeScript 代码示例演示策略模式的核心结构:

typescript
// 策略接口
interface Strategy {
  calculate(price: number): number;
}

// 具体策略A:不打折
class NormalStrategy implements Strategy {
  calculate(price: number): number {
    return price;
  }
}

// 具体策略B:满 100 减 20
class DiscountStrategy implements Strategy {
  calculate(price: number): number {
    return price >= 100 ? price - 20 : price;
  }
}

// 具体策略C:打 8 折
class RebateStrategy implements Strategy {
  calculate(price: number): number {
    return price * 0.8;
  }
}

// 上下文:用于切换和执行策略
class PriceContext {
  private strategy: Strategy;

  constructor(strategy: Strategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy: Strategy) {
    this.strategy = strategy;
  }

  getFinalPrice(price: number): number {
    return this.strategy.calculate(price);
  }
}

使用示例

假设在电商平台中,付款结算阶段需要根据用户选择的优惠方式来实时计算价格。演示代码如下:

typescript
// 创建策略对象
const normalStrategy = new NormalStrategy();
const discountStrategy = new DiscountStrategy();
const rebateStrategy = new RebateStrategy();

// 创建上下文
const priceContext = new PriceContext(normalStrategy);

// 初始使用无折扣策略
console.log('最终价格:', priceContext.getFinalPrice(120)); // 输出 120

// 切换为满减策略
priceContext.setStrategy(discountStrategy);
console.log('最终价格:', priceContext.getFinalPrice(120)); // 输出 100

// 切换为打折策略
priceContext.setStrategy(rebateStrategy);
console.log('最终价格:', priceContext.getFinalPrice(120)); // 输出 96

优缺点

优点

  • 易扩展:每种具体策略都封装在各自的类中,新增或更改策略轻松便捷。
  • 职责单一:消除了冗长的 if-else 或 switch-case 语句,逻辑更清晰。
  • 避免耦合:将算法独立于上下文环境,算法自由替换或复用。

缺点

  • 对象数量增多:每一种算法需要多一个类,可能导致类爆炸。
  • 策略选择成本:需要知道所有策略的差异,并选择合适策略。

总结

策略模式非常适合需要在运行时灵活切换算法的场景,比如多种优惠计算、多种排序策略、多种日志记录策略等。它很好地遵循了“开闭原则”,在增加新策略时无需修改已存在的上下文逻辑。

在实际开发中,如果面对大量“if-else 逻辑”或“switch-case 逻辑”,并且这些分支逻辑还能抽象为几种算法选项时,就可以考虑用策略模式来简化结构、降低耦合,让代码更灵活、更易维护。