策略模式

classDiagram
class Context {
-strategy: Strategy
+setStrategy(strategy: Strategy)
+executeStrategy()
}

class Strategy {
<<interface>>
+execute(data)
}

class ConcreteStrategyA {
+execute(data)
}

class ConcreteStrategyB {
+execute(data)
}

Context --> Strategy : uses
Strategy <|-- ConcreteStrategyA
Strategy <|-- ConcreteStrategyB

策略模式常用于那些需要频繁添加新的处理逻辑但是系统整体执行流程不需要发生变化的场合。

例如,一个大商场经常组织各种各样的促销活动,不同促销活动下商品的价格计算方式有所不同,但商场整体的处理逻辑仍然是:顾客挑选商品 -> 商品打包下单 -> 计算价格 -> 生产订单 -> 支付 -> 打印报表等,其中计算价格就是不同促销活动有所不同的地方,需要频繁添加新的计算逻辑,这个场合下就非常适合策略模式。

模式动机

如果存在许多不同的算法实现相同的逻辑,直接硬编码进代码中(比如大量if-else)会使系统难以扩展,不可接受。

当满足以下条件时,考虑使用策略模式:

  • 许多相关的类只在行为上有所不同
  • 当你需要不同算法的变体时
  • 当算法使用客户端不该知道的数据时,用策略模式避免将数据结构暴露于算法
  • 一个类定义了许多行为,在实现上表现为多个条件语句——不要使用多个条件语句,而是将相关条件分支变成策略类

影响

  1. 策略层次结构定义了一组算法或行为供上下文重用,可以帮助提取算法的公共功能
  2. 子类化的替代方案(多种策略可选)
  3. 策略消除了条件判断

缺点

  1. 客户端必须了解不同策略之间的差异,这可能会暴露实现
  2. 策略和上下文之间的通信开销变大
  3. 对象数量增加