比方说,我们整个框架的流程是接收数据、处理数据、返回数据。但是在如何处理数据这个问题上,我们有不同的解决办法。
所以这时,我们可以将“如何处理数据”这一模块抽象出来,抽象为 strategy interface,其包含 process_data(data) -> data 方法.这样对于整个框架来说,它就不需要去考虑“处理数据”这一板块内部如何实现、采用什么算法之类的,只需要调用 .process_data() 接口就可以正常推进流程了.
Overview
classDiagram
%% 策略接口
class Strategy {
<>
+execute(data)
}
%% 具体策略类
class ConcreteStrategyA {
+execute(data)
}
class ConcreteStrategyB {
+execute(data)
}
%% 上下文类
class Context {
-strategy: Strategy
+setStrategy(strategy: Strategy)
+doSomething()
}
%% 客户端类
class Client
%% 关系定义
Strategy <|.. ConcreteStrategyA : 实现
Strategy <|.. ConcreteStrategyB : 实现
Context o-- Strategy : 聚合
Client ..> Context : 依赖
Context 对象就是我们前面的“框架”,其内部有一个 Strategy interface 对象.ConcreteStrategyA, ConcreteStrategyB 实现了 Strategy 接口,可以对 Context 中的 Strategy 对象进行替换.Client 对象可以实例化 StrategyA,B 并调用 setStrategy() 对策略进行替换.
运行逻辑
sequenceDiagram
participant Client
participant Context
participant Strategy
Client->>ConcreteStrategy: new ConcreteStrategy()
activate ConcreteStrategy
Client->>Context: new Context()
activate Context
Client->>Context: setStrategy(strategy)
Note right of Context: 持有策略引用
Client->>Context: doSomething()
Context->>Strategy: execute(data)
activate Strategy
Strategy-->>Context: 返回结果
deactivate Strategy
Context-->>Client: 返回结果
deactivate Context
deactivate ConcreteStrategy
与 Template Method 设计模式的区别
Strategy 设计模式的被调用者是 Context,而 Context 里的 Strategy 可以被替换.因此总的来说,Strategy 设计模式依靠组合、可替换、运行时选择.
而 Template Method 的实际被调用者是 ConcreteClassX,即 Template Method 的具体实现.而 Template Method 的步骤流程其实是固定的,所以 Template Method 的本质是依靠继承、固定流程、步骤可变完成.