策略模式

行为型模式

访问次数: 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