核心思想
- 策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列算法或策略,将它们封装成独立的类,并使它们可以相互替换,而不影响客户端的代码,提高代码的可维护性和扩展性。

结构
1. Strategy(抽象策略接口)
- 定义一些列可供替换的算法方法。
2. ConcreteStrategy(具体策略实现)
- 实现不同的算法或行为。
3. Context(上下文)
- 持有策略对象,并在需要时调用具体策略的方法。

适用场景
- **动态切换:**想使用不同的算法,并希望在运行时切换。
- 避免条件语句(如 if-else****或 switch-case**):**使用策略模式代替这些语句。
- **需要经常扩展算法或策略:**新策略的引入只需要实现策略接口并添加到上下文中,而不需要改动现有的算法逻辑。
- 算法的独立性: 如果某些算法或操作的实现与具体的上下文和客户端无关,而仅依赖于传入的参数,策略模式能很好地将算法从客户端解耦出来。
优缺点
优点:
- 符合开闭原则:无需对 Context 进行修改就能引入新的策略。
- 运行时切换:可以在运行时切换对象内的算法。
- **解耦:**上下文无需关心具体的策略实现。
- **减少 if-else 的使用:**避免大量条件判断,提高可读性和可维护性。
缺点:
- 增加类数量:每个策略需要定义一个新的类,可能会类爆炸。
- 策略切换成本:客户端必须手动指定策略,无法动态适配。
实现步骤
- 从上下文类中找出修改频率较高的算法 (也可能是用于在运行时选择某个算法变体的复杂条件运算符)。
- 声明该算法所有变体的通用策略接口。
- 将算法逐一抽取到各自的类中, 它们都必须实现策略接口。
- 在上下文类中添加一个成员变量用于保存对于策略对象的引用。 然后提供设置器以修改该成员变量。 上下文仅可通过策略接口同策略对象进行交互, 如有需要还可定义一个接口来让策略访问其数据。
- 客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。
示例

// 抽象策略接口
public interface Strategy {
void show();
}
// 具体策略------A
public class StrategyA implements Strategy{
@Override
public void show() {
System.out.println("具体策略A");
}
}
// 具体策略------B
public class StrategyB implements Strategy{
@Override
public void show() {
System.out.println("具体策略B");
}
}
// 具体策略------C
public class StrategyC implements Strategy{
@Override
public void show() {
System.out.println("具体策略C");
}
}
// 上下文
public class SalesMan {
// 持有一个抽象策略接口
private Strategy strategy;
// 构造方法,传入一个具体策略对象
public SalesMan(Strategy strategy) {
this.strategy = strategy;
}
// 封装后的策略方法
public void salesManShow() {
strategy.show();
}
}
// 测试类
public class Client {
public static void main(String[] args) {
SalesMan salesManA = new SalesMan(new StrategyA());
salesManA.salesManShow();
System.out.println("--------------------------------");
SalesMan salesManB = new SalesMan(new StrategyB());
salesManB.salesManShow();
System.out.println("--------------------------------");
SalesMan salesManC = new SalesMan(new StrategyC());
salesManC.salesManShow();
}
}
在源码中的应用




与其他模式的关系
- 桥接模式、 状态模式和策略模式 (在某种程度上包括适配器模式) 模式的接口非常相似。 实际上, 它们都基于组合模式------即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
- 命令模式和策略看上去很像, 因为两者都能通过某些行为来参数化对象。 但是, 它们的意图有非常大的不同。
-
- 你可以使用命 令来将任何操作转换为对象。 操作的参数将成为对象的成员变量。 你可以通过转换来延迟操作的执行、 将操作放入队列、 保存历史命令或者向远程服务发送命令等。
- 另一方面, 策 略通常可用于描述完成某件事的不同方式, 让你能够在同一个上下文类中切换算法。