注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

算法族的动态切换


1. 模式定义与用途

核心思想

  • 策略模式:定义算法族,将每个算法封装为独立类,使其可以互相替换,且算法的变化独立于使用它的客户端。
  • 关键用途
    ​1.消除条件分支:避免在代码中硬编码多种算法实现(如if-elseswitch-case)。
    ​2.运行时动态切换:通过替换策略对象灵活调整程序行为。
    ​3.简化单元测试:每个策略可独立测试。

经典场景

  • 支付方式选择(信用卡、支付宝、微信支付)。
  • 排序算法切换(快速排序、归并排序、冒泡排序)。
  • 数据压缩策略(ZIP、RAR、7z)。

2. 模式结构解析

UML类图

+---------------------------+                +---------------------+  
|      Context              |                |      Strategy       |  
+---------------------------+                +---------------------+  
| - strategy: Strategy      |<---------------| + execute(): void   |  
+---------------------------+                +---------------------+  
| + setStrategy(s: Strategy)|                           ^  
| + executeStrategy()       |                           |  
+---------------------------+                +----------+-----------+  
                                             |                      |  
                                   +-------------------+      +-------------------+  
                                   | ConcreteStrategyA |      | ConcreteStrategyB |  
                                   +-------------------+      +-------------------+  
                                   | + execute()       |      | + execute()       |  
                                   +-------------------+      +-------------------+  

角色说明

  1. Context:上下文类,持有一个策略对象引用,通过接口调用算法。
  2. Strategy:策略接口,定义算法的公共接口(如execute())。
  3. ConcreteStrategy:具体策略类,实现特定算法。

3. 现代C++实现示例

场景:支付方式动态切换

​步骤1:定义策略接口
#include <iostream>  
#include <memory>  

// 支付策略接口  
class PaymentStrategy {  
public:  
    virtual ~PaymentStrategy() = default;  
    virtual void pay(double amount) = 0;  
};  
步骤2:实现具体策略类
// 支付宝支付  
class AlipayStrategy : public PaymentStrategy {  
public:  
    void pay(double amount) override {  
        std::cout << "支付宝支付: ¥" << amount << "\n";  
    }  
};  

// 微信支付  
class WechatPayStrategy : public PaymentStrategy {  
public:  
    void pay(double amount) override {  
        std::cout << "微信支付: ¥" << amount << "\n";  
    }  
};  

// 信用卡支付  
class CreditCardStrategy : public PaymentStrategy {  
public:  
    void pay(double amount) override {  
        std::cout << "信用卡支付: ¥" << amount << "\n";  
    }  
};  
步骤3:实现上下文类(订单处理器)
class OrderProcessor {  
public:  
    explicit OrderProcessor(std::unique_ptr<PaymentStrategy> strategy)  
        : strategy_(std::move(strategy)) {}  

    void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strategy) {  
        strategy_ = std::move(strategy);  
    }  

    void checkout(double amount) {  
        strategy_->pay(amount);  
    }  

private:  
    std::unique_ptr<PaymentStrategy> strategy_;  
};  
步骤4:客户端代码
int main() {  
    // 初始使用支付宝  
    OrderProcessor processor(std::make_unique<AlipayStrategy>());  
    processor.checkout(100.0);  // 输出:支付宝支付: ¥100  

    // 动态切换为微信支付  
    processor.setPaymentStrategy(std::make_unique<WechatPayStrategy>());  
    processor.checkout(200.0);  // 输出:微信支付: ¥200  

    // 切换为信用卡支付  
    processor.setPaymentStrategy(std::make_unique<CreditCardStrategy>());  
    processor.checkout(300.0);  // 输出:信用卡支付: ¥300  
}  

4. 应用场景示例

场景1:排序算法切换

template <typename T>  
class SortStrategy {  
public:  
    virtual void sort(std::vector<T>& data) = 0;  
};  

class QuickSort : public SortStrategy<int> {  
    void sort(std::vector<int>& data) override { /* 快速排序实现 */ }  
};  

class MergeSort : public SortStrategy<int> {  
    void sort(std::vector<int>& data) override { /* 归并排序实现 */ }  
};  

// 上下文类  
class Sorter {  
public:  
    void setStrategy(std::unique_ptr<SortStrategy<int>> strategy) {  
        strategy_ = std::move(strategy);  
    }  
    void execute(std::vector<int>& data) {  
        strategy_->sort(data);  
    }  
private:  
    std::unique_ptr<SortStrategy<int>> strategy_;  
};  

场景2:数据加密策略

class EncryptionStrategy {  
public:  
    virtual std::string encrypt(const std::string& data) = 0;  
};  

class AESStrategy : public EncryptionStrategy {  
    std::string encrypt(const std::string& data) override { /* AES加密 */ }  
};  

class RSAStrategy : public EncryptionStrategy {  
    std::string encrypt(const std::string& data) override { /* RSA加密 */ }  
};  

// 使用示例  
class DataEncryptor {  
public:  
    void setStrategy(std::unique_ptr<EncryptionStrategy> strategy) {  
        strategy_ = std::move(strategy);  
    }  
    std::string process(const std::string& data) {  
        return strategy_->encrypt(data);  
    }  
private:  
    std::unique_ptr<EncryptionStrategy> strategy_;  
};  

5. 优缺点分析

​优点​缺点
避免条件分支,提升代码可维护性策略类数量增加(需为每个算法单独实现)
支持运行时动态切换算法客户端需理解不同策略的差异
符合开闭原则(扩展新策略无需修改现有代码)增加对象间通信开销(策略与上下文交互)

6. 调试与优化策略

调试技巧(VS2022)​

1. ​验证策略切换逻辑:
  • setStrategy()方法中设置断点,检查策略对象是否被正确替换。
2. ​跟踪策略执行路径:
  • 使用 ​调用堆栈 查看具体策略的execute()方法调用来源。

性能优化

1. 策略对象复用:
  • 若策略无状态,可设计为单例或静态对象,避免重复创建。
class AESStrategy : public EncryptionStrategy {  
public:  
    static AESStrategy& getInstance() {  
        static AESStrategy instance;  
        return instance;  
    }  
    // ...  
};  
2. 编译时策略选择(通过模板)​:
template <typename Strategy>  
class DataProcessor {  
public:  
    void process(const std::string& data) {  
        Strategy::execute(data);  
    }  
};  

// 使用示例  
DataProcessor<AESStrategy> processor;  
processor.process("data");  

与其他模式的区别

1. 与状态模式:

  • 策略模式:客户端主动切换策略,策略之间通常无关联。
  • 状态模式:状态转换由内部逻辑触发,状态间可能相互依赖。

2. 与命令模式:

  • 策略模式:聚焦算法替换,通常无撤销/重做需求。
  • 命令模式:封装操作请求,支持事务、队列和日志。

更多推荐