5.9-Strategy「Policy」-策略模式
目的
封装算法,使之可以独立于客户变化
示例
文本分行有多种算法
- 若将程序类包含多种算法的代码,则使程序庞杂难维护
- 并非任何时候都需要所有的算法
- 若将算法嵌入客户程序内部,则变更算法将十分困难

- Composition 维护对 Compositor 对象的一个引用。一旦 Composition 重新格式化它的文本,它就将这个职责转发给它的 Compositor 对象
- Compositor 的子类实现具体的分行算法
适用性
- 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
- 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。
- 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的 Strategy 类中以代替这些条件语句。
结构

- Strategy:算法的公共接口,Context 调用该接口
- ConcreteStrategy:实现具体的策略
- Context:用一个 ConcreteStrategy 对象来配置,维护一个 Strategy 实例,提供接口让 Strategy 访问其数据
Strategy 和 Context 相互作用以实现选定的算法。
- 客户仅与 Context 交互,通常创建并传递一个 Concrete-Strategy 对象给该 Context
- Context 将客户的请求转发给它的 Strategy。
- 当算法被调用时, Context 可以将该算法所需要的所有数据都传递给该 Strategy。
- 或者 Context 可以将自身作为一个参数传递给 Strategy 操作,以便 Strategy 在适当时候回调。
效果
- 降低 Context 的复杂度:将算法和 Context 解耦合,易于切换算法
- 有利于复用算法
- 允许客户根据具体的时间/空间需要选择具体算法,但相应地,这意味着需要客户了解不同的 Strategy 之间的差异
- 消除了大量的条件判断:Context 内嵌多种算法/行为时,通常需要大量条件语句来选择合适的行为 缺陷
- 冗余参数:不同的 ConcreteStrategy 需要不同的参数集,因此抽象父类定义的接口必须提供这些参数集的并集。
- 这就意味着有时 Context 会创建和初始化一些永远不会用到的参数
- 如果存在这样的问题,那么将需要在 Strategy 和 Context 之间进行更紧密的耦合。
- 对象的数目:Strategy 增加了一个应用中的对象的数目。有时你可以将 Strategy 实现为可供各 Context 共享的无状态的对象来减少这一开销
实现
关于 Strategy 和 Context 的接口
这些接口必须让 ConcreteStrategy 能够有效地访问它所需要的 Context 中的任何数据,实现上有两种方法:







