策略模式
行为型模式
访问次数: 9
策略模式定义了一系列算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。
视频教程
类图
classDiagram
class Strategy {
<<interface>>
+algorithm()
}
class ConcreteStrategyA {
+algorithm()
}
class ConcreteStrategyB {
+algorithm()
}
class ConcreteStrategyC {
+algorithm()
}
class Context {
-strategy: Strategy
+setStrategy(strategy: Strategy)
+executeStrategy()
}
Strategy <|-- ConcreteStrategyA
Strategy <|-- ConcreteStrategyB
Strategy <|-- ConcreteStrategyC
Context --> Strategy
源代码示例
// 策略接口
interface Strategy {
void algorithm();
}
// 具体策略A
class ConcreteStrategyA implements Strategy {
@Override
public void algorithm() {
System.out.println("ConcreteStrategyA algorithm");
}
}
// 具体策略B
class ConcreteStrategyB implements Strategy {
@Override
public void algorithm() {
System.out.println("ConcreteStrategyB algorithm");
}
}
// 具体策略C
class ConcreteStrategyC implements Strategy {
@Override
public void algorithm() {
System.out.println("ConcreteStrategyC algorithm");
}
}
// 上下文类
class Context {
private Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.algorithm();
}
}
# Python代码待添加
应用场景
当需要在运行时选择算法,或者需要避免使用多重条件判断时。应用场景包括:
1)支付系统中,根据不同的支付方式(支付宝、微信、银行卡)执行不同的支付算法
2)排序算法选择,根据数据规模和特点选择不同的排序策略(快速排序、归并排序、堆排序)
3)数据验证系统,根据不同的数据类型和规则选择相应的验证策略
4)压缩算法选择,根据文件类型和大小选择不同的压缩策略(ZIP、RAR、7Z)
5)路由算法选择,根据网络状况选择不同的路由策略(最短路径、负载均衡、故障转移)
6)缓存策略选择,根据数据访问模式选择不同的缓存策略(LRU、LFU、FIFO)
精选场景详解 —— 支付收银台:运行时切换支付算法
问题背景
结算时按支付宝、微信、银行卡走不同签名、下单、回调流程。用大量 if-else 选择算法,难扩展也难单测。
模式如何解决
选用策略模式:PaymentStrategy 定义 pay 算法接口;AlipayStrategy 等为实现;CheckoutContext 持有当前策略,可 setStrategy 后执行。
与简单工厂常配合:工厂负责创建策略实例,上下文负责在业务中使用策略。
与状态模式区别:策略由调用方主动选择,状态通常由对象内部流转触发。支付「选渠道」是典型策略;订单「待支付→已支付」是状态。
场景模型(角色映射)
将模式中的抽象角色映射到该业务领域的具体类:
classDiagram
class PaymentStrategy {
<<interface>>
+pay(amount: decimal) PayResult
}
class AlipayStrategy {
+pay(amount: decimal) PayResult
}
class WeChatStrategy {
+pay(amount: decimal) PayResult
}
class BankCardStrategy {
+pay(amount: decimal) PayResult
}
class CheckoutContext {
-strategy: PaymentStrategy
+setStrategy(s: PaymentStrategy)
+execute(amount: decimal) PayResult
}
class CashierUI {
+onUserSelectChannel(channel: String)
}
PaymentStrategy <|.. AlipayStrategy
PaymentStrategy <|.. WeChatStrategy
PaymentStrategy <|.. BankCardStrategy
CheckoutContext --> PaymentStrategy
CashierUI --> CheckoutContext