策略模式
# 策略模式
# 一、策略模式
原理:策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
优缺点
- 1 优点
- 符合开闭原则:可以在不修改原有代码的情况下增加新的策略算法,实现了对扩展开放,对修改封闭。
- 消除条件语句:将算法的实现分离成独立的策略类,避免了在客户端代码中使用大量的条件语句(如
if-else
或switch-case
)。 - 提高代码复用性:不同的策略可以被不同的客户端重复使用,减少了代码的重复。
- 提高算法的可维护性:将复杂的算法逻辑封装在独立的策略类中,使得每个策略类的职责单一,便于维护和管理。
- 提高代码的可读性:通过将不同的算法分开,实现了职责单一,使得代码更加清晰易懂。
- 2 缺点
- 增加类的数量:每一个具体策略都是一个新的类,可能会导致类的数量大幅增加,增加了系统的复杂性。
- 客户端必须了解所有策略:客户端需要知道所有的策略,并且需要自行选择合适的策略,这增加了客户端的复杂度。
- 策略切换成本:如果需要动态地在策略之间切换,可能会增加一定的运行时开销,并且需要额外的逻辑来管理这些切换。
- 策略类可能会被滥用:如果策略类过多,可能会导致设计的混乱,使得系统变得难以理解和维护。
适用场景
- 需要在不同情况下使用不同的算法:例如,排序算法在不同的数据规模或数据分布情况下可能会有不同的选择。
- 算法的实现细节对客户端透明:客户端只需要知道策略接口,而不需要关心具体的实现细节。
- 算法有多种实现方式,且这些实现可能会频繁变化:例如,不同的压缩算法、不同的日志记录策略等。
# 二、策略模式基本代码
策略接口
public interface Strategy { void execute(String data); }
1
2
3具体策略类A,B
public class ConcreteStrategyA implements Strategy { @Override public void execute(String data) { System.out.println("Algorithm A processing " + data); } } public class ConcreteStrategyB implements Strategy { @Override public void execute(String data) { System.out.println("Algorithm B processing " + data); } }
1
2
3
4
5
6
7
8
9
10
11
12
13上下文类
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void executeStrategy(String data) { strategy.execute(data); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15客户端
public class StrategyPatternDemo { public static void main(String[] args) { // 使用策略 A Context context = new Context(new ConcreteStrategyA()); context.executeStrategy("data"); // 切换到策略 B context.setStrategy(new ConcreteStrategyB()); context.executeStrategy("data"); } }
1
2
3
4
5
6
7
8
9
10
11
# 三、实现方式
从上下文类中找出修改频率较高的算法 (也可能是用于在运行时选择某个算法变体的复杂条件运算符)。
声明该算法所有变体的通用策略接口。
将算法逐一抽取到各自的类中, 它们都必须实现策略接口。
在上下文类中添加一个成员变量用于保存对于策略对象的引用。 然后提供设置器以修改该成员变量。 上下文仅可通过策略接口同策略对象进行交互, 如有需要还可定义一个接口来让策略访问其数据。
客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。
编辑 (opens new window)