【C++设计模式】第二十篇:策略模式(Strategy)
·
注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。
算法族的动态切换
1. 模式定义与用途
核心思想
- 策略模式:定义算法族,将每个算法封装为独立类,使其可以互相替换,且算法的变化独立于使用它的客户端。
- 关键用途:
1.消除条件分支:避免在代码中硬编码多种算法实现(如if-else或switch-case)。
2.运行时动态切换:通过替换策略对象灵活调整程序行为。
3.简化单元测试:每个策略可独立测试。
经典场景
- 支付方式选择(信用卡、支付宝、微信支付)。
- 排序算法切换(快速排序、归并排序、冒泡排序)。
- 数据压缩策略(ZIP、RAR、7z)。
2. 模式结构解析
UML类图
+---------------------------+ +---------------------+
| Context | | Strategy |
+---------------------------+ +---------------------+
| - strategy: Strategy |<---------------| + execute(): void |
+---------------------------+ +---------------------+
| + setStrategy(s: Strategy)| ^
| + executeStrategy() | |
+---------------------------+ +----------+-----------+
| |
+-------------------+ +-------------------+
| ConcreteStrategyA | | ConcreteStrategyB |
+-------------------+ +-------------------+
| + execute() | | + execute() |
+-------------------+ +-------------------+
角色说明
Context:上下文类,持有一个策略对象引用,通过接口调用算法。Strategy:策略接口,定义算法的公共接口(如execute())。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. 与命令模式:
- 策略模式:聚焦算法替换,通常无撤销/重做需求。
- 命令模式:封装操作请求,支持事务、队列和日志。
更多推荐

所有评论(0)