> For the complete documentation index, see [llms.txt](https://anjia1.gitbook.io/design/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://anjia1.gitbook.io/design/patterns/behavioral/strategy.md).

# 策略模式

Strategy Design Pattern

> Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

* 定义了一个算法族，将每个算法分别封装起来，使得它们之间可以相互替换
* 让算法的变化独立于使用它的客户。

策略模式解耦的是策略的定义、创建、使用。

1. 策略的定义：包含一个策略接口和一组实现该接口的策略类（基于接口编程，方便运行时切换）
2. 策略的创建：由工厂类完成，封装策略创建的细节
3. 策略模式包含一组可选策略，选择使用哪个策略，有两种方法：
   * 编译时静态确定
   * 运行时动态确定：最典型的应用场景

eg1. 静态确定

```javascript
// 注意：并不能发挥策略模式的优势，此时策略模式实际上退化成了“面向对象的多态特性”或“基于接口而非实现编程原则”
EvictionStrategy evictionStrategy = new LruEvictionStrategy()
UserCache userCache = new UserCache(evictionStrategy)
```

eg2. 动态确定

```javascript
// 根据 type，用工厂创建
EvictionStrategy evictionStrategy = EvictionStrategyFactory.getEvictionStrategy(type)
UserCache userCache = new UserCache(evictionStrategy)
```

```js
OrderType type = order.getType()
DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type)
discountStrategy.calDiscount(order)
```

<figure><img src="https://1661549646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fv8LKbdX9taVYu96xrCAD%2Fuploads%2FJSKPIIOTvgSDd638KUfp%2Fimage.png?alt=media&amp;token=8894b339-2d6f-4c82-a104-488606d48d16" alt=""><figcaption><p>解耦：策略的定义、创建、使用</p></figcaption></figure>

<table><thead><tr><th width="211">设计原则</th><th>策略模式</th></tr></thead><tbody><tr><td>封装变化</td><td>变化的是：策略的定义，比如算法的内部实现、算法的数目</td></tr><tr><td>针对接口编程</td><td>一组策略类实现了相同的策略接口</td></tr><tr><td>优先使用组合</td><td>客户 has-a 策略接口</td></tr><tr><td>松耦合</td><td>策略的定义 vs 策略的使用</td></tr></tbody></table>
