参考文献

策略模式

  • 定义一系列算法,封装每个算法,并使它们可以互换.策略使算法能够独立于使用它的客户端而变化.

组件

  • Strategy(策略): 定义所有支持的算法通用的接口. Context 使用此接口来调用 ConcreteStrategy 定义的算法.
  • ConcreteStrategy(具体策略): 每个具体策略都实现一个算法.它们实现了 Strategy 接口定义的方法,提供了不同的算法实现
  • Context(上下文)
    • 包含对策略对象的引用.
    • 可以定义一个接口,让策略访问其数据.
  • Context 对象包含对应使用的ConcreteStrategy 的引用.当需要执行操作时,算法将从策略对象运行.上下文不知道策略的实施.如有必要,可以定义附加对象以将数据从上下文对象传递到策略.
  • 上下文对象接收来自客户端的请求并将它们委托给策略对象.通常,ConcreteStartegy 由客户端创建并传递到上下文.从此时起,客户端仅与上下文交互.

实现方式

  • 从上下文类中找出需要修改频率较高的算法,或者使用复杂条件运算符来选择算法变体.
  • 声明一个通用的策略接口,该接口定义了算法的方法.
  • 创建具体的策略类,对每个算法变体分别创建一个类,并让它们实现策略接口.每个具体策略类都包含了特定的算法实现.
  • 在上下文类中添加一个成员变量,用于保存对策略对象的引用.提供一个设置器方法,以便在运行时可以修改该成员变量的值.上下文类只能通过策略接口与策略对象进行交互,如果需要,还可以定义一个接口来让策略访问上下文类的数据.
  • 客户端必须将上下文类与相应的策略进行关联,这样上下文类才能按预期方式完成其主要工作.客户端可以通过设置上下文类的策略对象来切换不同的算法实现.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 第一步:定义策略接口
interface Strategy {
void execute();
}

// 第二步:实现具体策略类
class ConcreteStrategyA implements Strategy {
public void execute() {
System.out.println("Executing strategy A");
}
}

class ConcreteStrategyB implements Strategy {
public void execute() {
System.out.println("Executing strategy B");
}
}

// 第三步:实现上下文类
class Context {
private Strategy strategy;

public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}

public void doWork() {
if (strategy != null) {
strategy.execute();
}
}
}

// 第四步:在客户端中使用策略模式
public class Main {
public static void main(String[] args) {
Context context = new Context();

Strategy strategyA = new ConcreteStrategyA();
context.setStrategy(strategyA);
context.doWork(); // 输出 "Executing strategy A"

Strategy strategyB = new ConcreteStrategyB();
context.setStrategy(strategyB);
context.doWork(); // 输出 "Executing strategy B"
}
}

使用场景

  • 当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法时,可以使用策略模式.
    • 该模式允许你定义多个策略(即算法变体),并将其封装在不同的策略类中.通过将具体策略对象传递给上下文对象,可以在运行时灵活地更改所使用的具体算法.
  • 当你有许多仅在执行某些行为时略有不同的相似类时,可以使用策略模式.
    • 通过将这些行为封装在具体策略类中,可以避免代码重复,并使每个类负责执行自己特定的行为.
  • 如果算法在上下文的逻辑中不是特别重要,使用策略模式能够将类的业务逻辑与其算法实现细节隔离开来.上下文对象只需调用策略接口的方法,而不需要了解具体策略的实现细节.这种解耦可以提高代码的可维护性和可扩展性.
  • 当类中使用了复杂的条件运算符以在同一算法的不同变体中切换时,使用策略模式可以提供更清晰、可读性更高的代码.通过将每个变体封装在具体策略类中,可以消除大量的条件判断,并使代码结构更加简洁明了.