1. 背景与核心概念
1.1 设计模式的起源与发展
策略模式作为经典的23种GoF设计模式之一,诞生于1994年的经典著作《设计模式:可复用面向对象软件的基础》。这本书由四位作者(Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)共同完成,被业界亲切地称为"四人帮"(Gang of Four)。
发展历程:
- 1994年:GoF首次系统化提出策略模式
- 2000年代:随着C++标准模板库(STL)的普及,函数对象成为实现策略模式的主流方式
- 2011年:C++11引入std::function和lambda表达式,为策略模式提供了更灵活的实现手段
- 至今:策略模式已成为现代C++开发中的基础设计模式
1.2 核心概念解析
策略模式的核心思想:将算法与使用算法的客户端解耦,让算法可以独立于客户端而变化。
关键术语:
- 策略接口(Strategy Interface):定义所有支持算法的公共接口
- 具体策略(Concrete Strategy):实现策略接口的具体算法类
- 上下文(Context):持有一个策略对象的引用,通过策略接口与具体策略交互
1.3 UML类图展示
让我们通过Mermaid UML类图来直观理解策略模式的结构:
Context -strategy: Strategy* +setStrategy(Strategy*) +executeStrategy() : void <<interface>> Strategy +execute() : void ConcreteStrategyA +execute() : void ConcreteStrategyB +execute() : void ConcreteStrategyC +execute() : void
2. 设计意图与考量
2.1 核心设计目标
策略模式主要解决以下问题:
- 消除条件语句:避免在代码中使用大量的if-else或switch-case语句
- 开闭原则:对扩展开放,对修改封闭,新增算法无需修改现有代码
- 算法复用:相同的算法可以在不同的环境中重用
2.2 设计权衡因素
优势:
- 符合单一职责原则:每个算法都有自己的类
- 符合开闭原则:无需修改上下文即可引入新策略
- 算法可以自由替换
- 易于单元测试
劣势:
- 客户端必须了解不同策略的区别
- 增加了对象数量
- 策略对象间的通信可能变得复杂
2.3 C++中的特殊实现考量
在C++中,策略模式有几种典型的实现方式:
cpp
// 方式1:传统面向对象(基于继承)
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(std::vector<int>& data) = 0;
};
// 方式2:基于函数对象(Functor)
struct QuickSort {
void operator()(std::vector<int>& data) const {
// 快速排序实现
}
};
// 方式3:基于std::function(最灵活)
using SortStrategy = std::function<void(std::vector<int>&)>;
3. 实例与应用场景
3.1 案例一:排序算法策略
这是一个经典的策略模式应用场景,展示如何在不同排序算法间动态切换。
完整代码实现
SortStrategy.h
cpp
/**
* @file SortStrategy.h
* @brief 排序策略接口定义
*/
#ifndef SORT_STRATEGY_H
#define SORT_STRATEGY_H
#include <vector>
#include <functional>
#include <memory>
/**
* @brief 排序策略接口类
*
* 定义所有排序算法必须实现的接口,使用现代C++的std::function
* 提供更大的灵活性,支持函数对象、lambda表达式等
*/
class SortStrategy {
public:
virtual ~SortStrategy() = default;
/**
* @brief 执行排序操作
*
* 对输入的整数向量进行原地排序
*
* @inout:
* - data: 待排序的整数向量,排序后内容会被修改
*
* @return:
* 无返回值,排序结果直接反映在输入参数中
*/
virtual void sort(std::vector<int>& data) = 0;
};
/**
* @brief 快速排序策略
*
* 实现快速排序算法,平均时间复杂度O(n log n)
* 使用分治策略,适合大规模数据排序
*/
class QuickSortStrategy : public SortStrategy {
public:
void sort(std::vector<int>& data) override;
private:
void quickSort(std::vector<int>& data, int low, int high);
int partition(std::vector<int>& data, int low, int high);
};
/**
* @brief 冒泡排序策略
*
* 实现冒泡排序算法,时间复杂度O(n²)
* 实现简单,适合小规模数据或教育用途
*/
class BubbleSortStrategy : public SortStrategy {
public:
void sort(std::vector<int>& data) override;
};
/**
* @brief 归并排序策略
*
* 实现归并排序算法,时间复杂度O(n log n)
* 稳定排序算法,适合链表排序或外部排序
*/
class MergeSortStrategy : public SortStrategy {
public:
void sort(std::vector<int>& data) override;
private:
void mergeSort(std::vector<int>& data, int left, int right);
void merge(std::vector<int>& data, int left, int mid, int right);
};
/**
* @brief 排序上下文类
*
* 负责维护排序策略的引用,客户端通过此类与策略交互
* 支持运行时动态切换排序策略
*/
class SorterContext {
public:
/**
* @brief 设置排序策略
*
* 在运行时动态设置要使用的排序算法
*
* @in:
* - strategy: 排序策略的unique_ptr,所有权转移给上下文
*
* @out:
* - m_strategy: 更新内部保存的排序策略
*
* @return:
* 无返回值
*/
void setStrategy(std::unique_ptr<SortStrategy> strategy);
/**
* @brief 执行排序
*
* 使用当前设置的策略对数据进行排序
*
* @inout:
* - data: 待排序数据,排序后会被修改
*
* @return:
* 无返回值
*/
void executeSort(std::vector<int>& data);
/**
* @brief 获取当前策略名称
*
* 用于调试和显示当前使用的排序策略
*
* @return:
* 返回当前策略的类型名称字符串
*/
std::string getStrategyName() const;
private:
std::unique_ptr<SortStrategy> m_strategy; ///< 当前使用的排序策略
};
#endif // SORT_STRATEGY_H
SortStrategy.cpp
cpp
/**
* @file SortStrategy.cpp
* @brief 排序策略具体实现
*/
#include "SortStrategy.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <typeinfo>
// 快速排序策略实现
void QuickSortStrategy::sort(std::vector<int>& data) {
if (data.empty()) return;
quickSort(data, 0, data.size() - 1);
}
void QuickSortStrategy::quickSort(std::vector<int>& data, int low, int high) {
if (low < high) {
int pivot = partition(data, low, high);
quickSort(data, low, pivot - 1);
quickSort(data, pivot + 1, high);
}
}
int QuickSortStrategy::partition(std::vector<int>& data, int low, int high) {
int pivot = data[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (data[j] <= pivot) {
i++;
std::swap(data[i], data[j]);
}
}
std::swap(data[i + 1], data[high]);
return i + 1;
}
// 冒泡排序策略实现
void BubbleSortStrategy::sort(std::vector<int>& data) {
int n = data.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (data[j] > data[j + 1]) {
std::swap(data[j], data[j + 1]);
}
}
}
}
// 归并排序策略实现
void MergeSortStrategy::sort(std::vector<int>& data) {
if (data.empty()) return;
mergeSort(data, 0, data.size() - 1);
}
void MergeSortStrategy::mergeSort(std::vector<int>& data, int left, int right) {
if (left >= right) return;
int mid = left + (right - left) / 2;
mergeSort(data, left, mid);
mergeSort(data, mid + 1, right);
merge(data, left, mid, right);
}
void MergeSortStrategy::merge(std::vector<int>& data, int left, int mid, int right) {
std::vector<int> leftArr(data.begin() + left, data.begin() + mid + 1);
std::vector<int> rightArr(data.begin() + mid + 1, data.begin() + right + 1);
int i = 0, j = 0, k = left;
while (i < leftArr.size() && j < rightArr.size()) {
if (leftArr[i] <= rightArr[j]) {
data[k] = leftArr[i];
i++;
} else {
data[k] = rightArr[j];
j++;
}
k++;
}
while (i < leftArr.size()) {
data[k] = leftArr[i];
i++;
k++;
}
while (j < rightArr.size()) {
data[k] = rightArr[j];
j++;
k++;
}
}
// 排序上下文实现
void SorterContext::setStrategy(std::unique_ptr<SortStrategy> strategy) {
m_strategy = std::move(strategy);
}
void SorterContext::executeSort(std::vector<int>& data) {
if (m_strategy) {
m_strategy->sort(data);
} else {
std::cerr << "错误:未设置排序策略!" << std::endl;
}
}
std::string SorterContext::getStrategyName() const {
if (!m_strategy) return "无策略";
// 使用typeid获取具体类型名称
std::string name = typeid(*m_strategy).name();
// 清理name(不同编译器返回格式不同)
if (name.find("QuickSortStrategy") != std::string::npos) {
return "快速排序";
} else if (name.find("BubbleSortStrategy") != std::string::npos) {
return "冒泡排序";
} else if (name.find("MergeSortStrategy") != std::string::npos) {
return "归并排序";
}
return "未知策略";
}
main.cpp
cpp
/**
* @file main.cpp
* @brief 排序策略模式演示程序
*
* 展示策略模式在排序算法选择中的应用,支持运行时动态切换排序策略
*/
#include "SortStrategy.h"
#include <iostream>
#include <vector>
#include <random>
#include <memory>
/**
* @brief 生成随机测试数据
*
* 生成指定大小的随机整数向量,用于测试排序算法
*
* @in:
* - size: 向量大小
* - minVal: 最小值(包含)
* - maxVal: 最大值(包含)
*
* @return:
* 返回包含随机整数的vector
*/
std::vector<int> generateTestData(int size, int minVal = 1, int maxVal = 1000) {
std::vector<int> data;
data.reserve(size);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(minVal, maxVal);
for (int i = 0; i < size; i++) {
data.push_back(dis(gen));
}
return data;
}
/**
* @brief 打印向量内容
*
* 以可读格式输出向量内容,支持限制输出元素数量
*
* @in:
* - data: 要打印的向量
* - maxElements: 最大输出元素数(0表示全部输出)
*
* @return:
* 无返回值
*/
void printVector(const std::vector<int>& data, int maxElements = 10) {
std::cout << "[";
int count = 0;
for (int value : data) {
if (maxElements > 0 && count >= maxElements) {
std::cout << "...";
break;
}
std::cout << value;
if (count < static_cast<int>(data.size()) - 1 &&
(maxElements == 0 || count < maxElements - 1)) {
std::cout << ", ";
}
count++;
}
std::cout << "]" << std::endl;
}
/**
* @brief 测试排序策略性能
*
* 对指定排序策略进行性能测试,测量排序执行时间
*
* @in:
* - context: 排序上下文
* - testData: 测试数据
* - strategyName: 策略名称(用于输出)
*
* @return:
* 无返回值
*/
void testSortPerformance(SorterContext& context, std::vector<int> testData,
const std::string& strategyName) {
std::cout << "\n=== 测试 " << strategyName << " ===" << std::endl;
std::cout << "排序前数据(前10个): ";
printVector(testData, 10);
auto start = std::chrono::high_resolution_clock::now();
context.executeSort(testData);
auto end = std::chrono::high_resolution_clock::now();
std::cout << "排序后数据(前10个): ";
printVector(testData, 10);
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "排序耗时: " << duration.count() << " 微秒" << std::endl;
// 验证排序结果
bool isSorted = std::is_sorted(testData.begin(), testData.end());
std::cout << "排序验证: " << (isSorted ? "✓ 成功" : "✗ 失败") << std::endl;
}
int main() {
std::cout << "======= 排序策略模式演示 =======" << std::endl;
// 生成测试数据
const int DATA_SIZE = 1000;
auto testData = generateTestData(DATA_SIZE);
std::cout << "生成测试数据大小: " << DATA_SIZE << std::endl;
SorterContext sorter;
// 测试快速排序
sorter.setStrategy(std::make_unique<QuickSortStrategy>());
testSortPerformance(sorter, testData, sorter.getStrategyName());
// 测试冒泡排序
sorter.setStrategy(std::make_unique<BubbleSortStrategy>());
testSortPerformance(sorter, testData, sorter.getStrategyName());
// 测试归并排序
sorter.setStrategy(std::make_unique<MergeSortStrategy>());
testSortPerformance(sorter, testData, sorter.getStrategyName());
std::cout << "\n======= 演示结束 =======" << std::endl;
return 0;
}
核心逻辑流程图
开始 生成测试数据 创建排序上下文 设置快速排序策略 执行快速排序测试 设置冒泡排序策略 执行冒泡排序测试 设置归并排序策略 执行归并排序测试 输出性能对比结果 结束 记录开始时间 执行排序算法 记录结束时间 计算耗时 验证排序结果
Makefile
makefile
# 编译器设置
CXX := g++
CXXFLAGS := -std=c++17 -Wall -Wextra -O2 -g
TARGET := sort_strategy_demo
# 源文件和目标文件
SRCS := main.cpp SortStrategy.cpp
OBJS := $(SRCS:.cpp=.o)
HEADERS := SortStrategy.h
# 默认目标
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)
# 编译规则
%.o: %.cpp $(HEADERS)
$(CXX) $(CXXFLAGS) -c $< -o $@
# 清理规则
clean:
rm -f $(OBJS) $(TARGET)
# 安装依赖(如果需要)
install-deps:
@echo "确保已安装g++ (版本 >= 7.0) 和 make"
# 运行测试
test: $(TARGET)
./$(TARGET)
# 显示帮助信息
help:
@echo "可用目标:"
@echo " make 编译程序"
@echo " make clean 清理编译结果"
@echo " make test 编译并运行程序"
@echo " make help 显示此帮助信息"
.PHONY: clean install-deps test help
操作说明
编译方法:
bash
# 确保系统已安装g++编译器(版本7.0或以上)
make clean && make
运行方式:
bash
./sort_strategy_demo
预期输出:
======= 排序策略模式演示 =======
生成测试数据大小: 1000
=== 测试 快速排序 ===
排序前数据(前10个): [542, 123, 876, 234, 765, 432, ...]
排序后数据(前10个): [1, 2, 3, 4, 5, 6, ...]
排序耗时: 1564 微秒
排序验证: ✓ 成功
=== 测试 冒泡排序 ===
排序前数据(前10个): [542, 123, 876, 234, 765, 432, ...]
排序后数据(前10个): [1, 2, 3, 4, 5, 6, ...]
排序耗时: 89234 微秒
排序验证: ✓ 成功
=== 测试 归并排序 ===
排序前数据(前10个): [542, 123, 876, 234, 765, 432, ...]
排序后数据(前10个): [1, 2, 3, 4, 5, 6, ...]
排序耗时: 1876 微秒
排序验证: ✓ 成功
======= 演示结束 =======
结果解读:
- 正常输出:显示三种排序算法的执行时间和排序结果验证
- 性能对比:快速排序和归并排序通常比冒泡排序快很多
- 异常提示:如果未设置策略会显示"错误:未设置排序策略!"
3.2 案例二:支付系统策略
这个案例展示在电商系统中如何灵活切换不同的支付方式。
完整代码实现
PaymentStrategy.h
cpp
/**
* @file PaymentStrategy.h
* @brief 支付策略接口定义
*/
#ifndef PAYMENT_STRATEGY_H
#define PAYMENT_STRATEGY_H
#include <iostream>
#include <memory>
#include <string>
/**
* @brief 支付请求结构体
*
* 包含支付所需的所有信息,传递给支付策略执行
*/
struct PaymentRequest {
std::string orderId; ///< 订单ID
double amount; ///< 支付金额
std::string currency; ///< 货币类型
std::string customerId; ///< 客户ID
PaymentRequest(const std::string& order, double amt,
const std::string& curr = "CNY",
const std::string& customer = "")
: orderId(order), amount(amt), currency(curr), customerId(customer) {}
};
/**
* @brief 支付结果结构体
*
* 包含支付执行的结果信息
*/
struct PaymentResult {
bool success; ///< 支付是否成功
std::string transactionId; ///< 交易ID
std::string message; ///< 结果消息
PaymentResult(bool succ = false,
const std::string& transId = "",
const std::string& msg = "")
: success(succ), transactionId(transId), message(msg) {}
};
/**
* @brief 支付策略接口
*
* 定义所有支付方式必须实现的接口
*/
class PaymentStrategy {
public:
virtual ~PaymentStrategy() = default;
/**
* @brief 执行支付
*
* 根据支付请求执行具体的支付操作
*
* @in:
* - request: 支付请求信息
*
* @return:
* 返回支付结果,包含成功状态和交易信息
*/
virtual PaymentResult pay(const PaymentRequest& request) = 0;
/**
* @brief 获取支付方式名称
*
* @return:
* 返回支付方式的显示名称
*/
virtual std::string getName() const = 0;
};
/**
* @brief 支付宝支付策略
*/
class AlipayStrategy : public PaymentStrategy {
public:
PaymentResult pay(const PaymentRequest& request) override;
std::string getName() const override { return "支付宝"; }
};
/**
* @brief 微信支付策略
*/
class WechatPayStrategy : public PaymentStrategy {
public:
PaymentResult pay(const PaymentRequest& request) override;
std::string getName() const override { return "微信支付"; }
};
/**
* @brief 信用卡支付策略
*/
class CreditCardStrategy : public PaymentStrategy {
public:
PaymentResult pay(const PaymentRequest& request) override;
std::string getName() const override { return "信用卡"; }
private:
std::string simulateBankProcessing(const PaymentRequest& request);
};
/**
* @brief 支付上下文类
*
* 管理支付策略,提供统一的支付接口
*/
class PaymentContext {
public:
/**
* @brief 设置支付策略
*/
void setStrategy(std::unique_ptr<PaymentStrategy> strategy);
/**
* @brief 执行支付操作
*
* @in:
* - request: 支付请求
*
* @return:
* 返回支付结果
*/
PaymentResult executePayment(const PaymentRequest& request);
/**
* @brief 获取当前支付方式名称
*/
std::string getCurrentMethod() const;
private:
std::unique_ptr<PaymentStrategy> m_strategy;
};
#endif // PAYMENT_STRATEGY_H
PaymentStrategy.cpp
cpp
/**
* @file PaymentStrategy.cpp
* @brief 支付策略具体实现
*/
#include "PaymentStrategy.h"
#include <random>
#include <sstream>
// 支付宝支付实现
PaymentResult AlipayStrategy::pay(const PaymentRequest& request) {
std::cout << "🔵 支付宝支付处理中..." << std::endl;
std::cout << " 订单: " << request.orderId << std::endl;
std::cout << " 金额: " << request.amount << " " << request.currency << std::endl;
// 模拟支付处理
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// 生成模拟交易ID
std::stringstream ss;
ss << "ALIPAY_" << request.orderId << "_" << std::time(nullptr);
// 模拟90%的成功率
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(0.0, 1.0);
bool success = dis(gen) > 0.1; // 90%成功率
if (success) {
return PaymentResult(true, ss.str(), "支付宝支付成功");
} else {
return PaymentResult(false, "", "支付宝支付失败:余额不足");
}
}
// 微信支付实现
PaymentResult WechatPayStrategy::pay(const PaymentRequest& request) {
std::cout << "🟢 微信支付处理中..." << std::endl;
std::cout << " 订单: " << request.orderId << std::endl;
std::cout << " 金额: " << request.amount << " " << request.currency << std::endl;
// 模拟支付处理
std::this_thread::sleep_for(std::chrono::milliseconds(400));
// 生成模拟交易ID
std::stringstream ss;
ss << "WECHAT_" << request.orderId << "_" << std::time(nullptr);
// 模拟95%的成功率
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(0.0, 1.0);
bool success = dis(gen) > 0.05; // 95%成功率
if (success) {
return PaymentResult(true, ss.str(), "微信支付成功");
} else {
return PaymentResult(false, "", "微信支付失败:网络异常");
}
}
// 信用卡支付实现
PaymentResult CreditCardStrategy::pay(const PaymentRequest& request) {
std::cout << "🟣 信用卡支付处理中..." << std::endl;
std::cout << " 订单: " << request.orderId << std::endl;
std::cout << " 金额: " << request.amount << " " << request.currency << std::endl;
// 模拟银行处理
std::string bankResponse = simulateBankProcessing(request);
if (bankResponse == "APPROVED") {
std::stringstream ss;
ss << "CC_" << request.orderId << "_" << std::time(nullptr);
return PaymentResult(true, ss.str(), "信用卡支付成功");
} else {
return PaymentResult(false, "", "信用卡支付失败:" + bankResponse);
}
}
std::string CreditCardStrategy::simulateBankProcessing(const PaymentRequest& request) {
std::this_thread::sleep_for(std::chrono::milliseconds(800));
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(0.0, 1.0);
double randomValue = dis(gen);
if (randomValue > 0.15) { // 85%批准率
return "APPROVED";
} else if (randomValue > 0.05) { // 10%拒绝率
return "DECLINED";
} else { // 5%系统错误
return "SYSTEM_ERROR";
}
}
// 支付上下文实现
void PaymentContext::setStrategy(std::unique_ptr<PaymentStrategy> strategy) {
m_strategy = std::move(strategy);
}
PaymentResult PaymentContext::executePayment(const PaymentRequest& request) {
if (!m_strategy) {
return PaymentResult(false, "", "未设置支付策略");
}
std::cout << "\n💳 开始支付流程..." << std::endl;
std::cout << "支付方式: " << m_strategy->getName() << std::endl;
auto result = m_strategy->pay(request);
std::cout << "支付结果: " << (result.success ? "✅ 成功" : "❌ 失败") << std::endl;
if (!result.message.empty()) {
std::cout << "结果信息: " << result.message << std::endl;
}
if (result.success && !result.transactionId.empty()) {
std::cout << "交易ID: " << result.transactionId << std::endl;
}
return result;
}
std::string PaymentContext::getCurrentMethod() const {
return m_strategy ? m_strategy->getName() : "未设置";
}
payment_demo.cpp
cpp
/**
* @file payment_demo.cpp
* @brief 支付策略演示程序
*/
#include "PaymentStrategy.h"
#include <iostream>
#include <memory>
#include <vector>
/**
* @brief 模拟电商支付流程
*/
void simulateEcommercePayment() {
std::cout << "🛒 === 电商支付系统演示 ===" << std::endl;
PaymentContext paymentContext;
PaymentRequest request("ORDER_2024_001", 299.99, "CNY", "CUST_1001");
// 测试支付宝支付
std::cout << "\n📱 场景1: 客户选择支付宝支付" << std::endl;
paymentContext.setStrategy(std::make_unique<AlipayStrategy>());
paymentContext.executePayment(request);
// 测试微信支付
std::cout << "\n📱 场景2: 客户选择微信支付" << std::endl;
paymentContext.setStrategy(std::make_unique<WechatPayStrategy>());
paymentContext.executePayment(request);
// 测试信用卡支付
std::cout << "\n💳 场景3: 客户选择信用卡支付" << std::endl;
paymentContext.setStrategy(std::make_unique<CreditCardStrategy>());
paymentContext.executePayment(request);
}
/**
* @brief 模拟支付策略动态切换
*/
void demonstrateDynamicSwitching() {
std::cout << "\n🔄 === 动态策略切换演示 ===" << std::endl;
PaymentContext context;
std::vector<PaymentRequest> orders = {
{"ORDER_2024_002", 150.50, "CNY", "CUST_1002"},
{"ORDER_2024_003", 89.99, "CNY", "CUST_1003"},
{"ORDER_2024_004", 450.00, "CNY", "CUST_1004"}
};
std::vector<std::unique_ptr<PaymentStrategy>> strategies;
strategies.push_back(std::make_unique<AlipayStrategy>());
strategies.push_back(std::make_unique<WechatPayStrategy>());
strategies.push_back(std::make_unique<CreditCardStrategy>());
for (size_t i = 0; i < orders.size(); ++i) {
std::cout << "\n--- 处理订单 " << (i + 1) << " ---" << std::endl;
context.setStrategy(std::move(strategies[i]));
context.executePayment(orders[i]);
// 重新创建策略对象以便下次使用
if (i == 0) strategies[i] = std::make_unique<AlipayStrategy>();
else if (i == 1) strategies[i] = std::make_unique<WechatPayStrategy>();
else strategies[i] = std::make_unique<CreditCardStrategy>();
}
}
/**
* @brief 统计支付成功率
*/
void analyzePaymentSuccessRate() {
std::cout << "\n📊 === 支付成功率分析 ===" << std::endl;
const int TEST_COUNT = 100;
std::vector<std::unique_ptr<PaymentStrategy>> strategies;
strategies.push_back(std::make_unique<AlipayStrategy>());
strategies.push_back(std::make_unique<WechatPayStrategy>());
strategies.push_back(std::make_unique<CreditCardStrategy>());
std::vector<std::string> strategyNames = {"支付宝", "微信支付", "信用卡"};
PaymentRequest testRequest("TEST_ORDER", 100.0);
for (size_t i = 0; i < strategies.size(); ++i) {
int successCount = 0;
std::cout << "\n测试 " << strategyNames[i] << " (" << TEST_COUNT << "次):" << std::endl;
for (int j = 0; j < TEST_COUNT; ++j) {
auto result = strategies[i]->pay(testRequest);
if (result.success) {
successCount++;
}
}
double successRate = (static_cast<double>(successCount) / TEST_COUNT) * 100;
std::cout << "成功次数: " << successCount << "/" << TEST_COUNT << std::endl;
std::cout << "成功率: " << successRate << "%" << std::endl;
}
}
int main() {
std::cout << "💰 支付策略模式演示程序" << std::endl;
std::cout << "=======================" << std::endl;
simulateEcommercePayment();
demonstrateDynamicSwitching();
analyzePaymentSuccessRate();
std::cout << "\n🎉 演示程序结束" << std::endl;
return 0;
}
支付流程时序图
客户端 PaymentContext PaymentStrategy 外部系统 setStrategy(支付策略) executePayment(支付请求) pay(支付请求) 策略特定处理 调用支付网关API 返回支付结果 返回PaymentResult 返回支付结果 根据结果更新UI 客户端 PaymentContext PaymentStrategy 外部系统
Makefile补充
在之前的Makefile基础上添加支付演示目标:
makefile
# 支付演示程序
PAYMENT_TARGET := payment_demo
PAYMENT_SRCS := payment_demo.cpp PaymentStrategy.cpp
PAYMENT_OBJS := $(PAYMENT_SRCS:.cpp=.o)
$(PAYMENT_TARGET): $(PAYMENT_OBJS)
$(CXX) $(CXXFLAGS) -o $(PAYMENT_TARGET) $(PAYMENT_OBJS) -lpthread
payment_demo.o: payment_demo.cpp PaymentStrategy.h
$(CXX) $(CXXFLAGS) -c payment_demo.cpp -o payment_demo.o
PaymentStrategy.o: PaymentStrategy.cpp PaymentStrategy.h
$(CXX) $(CXXFLAGS) -c PaymentStrategy.cpp -o PaymentStrategy.o
# 更新clean规则
clean:
rm -f $(OBJS) $(TARGET) $(PAYMENT_OBJS) $(PAYMENT_TARGET)
# 支付测试
test-payment: $(PAYMENT_TARGET)
./$(PAYMENT_TARGET)
操作说明
编译方法:
bash
make clean && make payment_demo
运行方式:
bash
./payment_demo
预期输出:
💰 支付策略模式演示程序
=======================
🛒 === 电商支付系统演示 ===
📱 场景1: 客户选择支付宝支付
💳 开始支付流程...
支付方式: 支付宝
🔵 支付宝支付处理中...
订单: ORDER_2024_001
金额: 299.99 CNY
支付结果: ✅ 成功
结果信息: 支付宝支付成功
交易ID: ALIPAY_ORDER_2024_001_1700000000
🔄 === 动态策略切换演示 ===
--- 处理订单 1 ---
💳 开始支付流程...
支付方式: 支付宝
🔵 支付宝支付处理中...
...
📊 === 支付成功率分析 ===
测试 支付宝 (100次):
成功次数: 89/100
成功率: 89%
🎉 演示程序结束
3.3 案例三:游戏角色攻击策略
这个案例展示在游戏开发中如何使用策略模式实现不同的攻击行为。
完整代码实现
AttackStrategy.h
cpp
/**
* @file AttackStrategy.h
* @brief 游戏角色攻击策略接口
*/
#ifndef ATTACK_STRATEGY_H
#define ATTACK_STRATEGY_H
#include <iostream>
#include <memory>
#include <string>
#include <random>
/**
* @brief 游戏角色类
*/
class GameCharacter {
public:
GameCharacter(const std::string& name, int health = 100)
: m_name(name), m_health(health) {}
std::string getName() const { return m_name; }
int getHealth() const { return m_health; }
void setHealth(int health) { m_health = health; }
void takeDamage(int damage) { m_health -= damage; }
private:
std::string m_name;
int m_health;
};
/**
* @brief 攻击策略接口
*/
class AttackStrategy {
public:
virtual ~AttackStrategy() = default;
/**
* @brief 执行攻击
*
* @in:
* - attacker: 攻击者角色
* - target: 目标角色
*
* @return:
* 返回造成的伤害值
*/
virtual int executeAttack(GameCharacter& attacker, GameCharacter& target) = 0;
/**
* @brief 获取策略名称
*/
virtual std::string getName() const = 0;
/**
* @brief 获取策略描述
*/
virtual std::string getDescription() const = 0;
};
/**
* @brief 近战攻击策略
*/
class MeleeAttack : public AttackStrategy {
public:
int executeAttack(GameCharacter& attacker, GameCharacter& target) override;
std::string getName() const override { return "近战攻击"; }
std::string getDescription() const override {
return "使用剑或斧头进行近距离物理攻击";
}
};
/**
* @brief 远程攻击策略
*/
class RangedAttack : public AttackStrategy {
public:
int executeAttack(GameCharacter& attacker, GameCharacter& target) override;
std::string getName() const override { return "远程攻击"; }
std::string getDescription() const override {
return "使用弓箭或枪械进行远距离攻击";
}
};
/**
* @brief 魔法攻击策略
*/
class MagicAttack : public AttackStrategy {
public:
int executeAttack(GameCharacter& attacker, GameCharacter& target) override;
std::string getName() const override { return "魔法攻击"; }
std::string getDescription() const override {
return "使用魔法咒语进行元素攻击";
}
};
/**
* @brief 偷袭策略
*/
class SneakAttack : public AttackStrategy {
public:
int executeAttack(GameCharacter& attacker, GameCharacter& target) override;
std::string getName() const override { return "偷袭"; }
std::string getDescription() const override {
return "从背后发动致命一击,有几率造成暴击";
}
};
/**
* @brief 角色战斗上下文
*/
class BattleContext {
public:
BattleContext(const std::string& characterName);
void setAttackStrategy(std::unique_ptr<AttackStrategy> strategy);
void attack(GameCharacter& target);
void displayStatus() const;
std::string getCurrentStrategy() const;
private:
GameCharacter m_character;
std::unique_ptr<AttackStrategy> m_attackStrategy;
};
#endif // ATTACK_STRATEGY_H
AttackStrategy.cpp
cpp
/**
* @file AttackStrategy.cpp
* @brief 攻击策略具体实现
*/
#include "AttackStrategy.h"
#include <random>
// 近战攻击实现
int MeleeAttack::executeAttack(GameCharacter& attacker, GameCharacter& target) {
std::cout << "⚔️ " << attacker.getName() << " 发动近战攻击!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> damageDis(15, 25);
std::uniform_real_distribution<double> hitDis(0.0, 1.0);
int damage = damageDis(gen);
double hitChance = hitDis(gen);
if (hitChance < 0.1) { // 10%几率miss
std::cout << " 💨 攻击未命中!" << std::endl;
return 0;
} else if (hitChance > 0.9) { // 10%几率暴击
damage *= 2;
std::cout << " 💥 暴击!造成 " << damage << " 点伤害!" << std::endl;
} else {
std::cout << " ✅ 命中!造成 " << damage << " 点伤害" << std::endl;
}
target.takeDamage(damage);
return damage;
}
// 远程攻击实现
int RangedAttack::executeAttack(GameCharacter& attacker, GameCharacter& target) {
std::cout << "🏹 " << attacker.getName() << " 发动远程攻击!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> damageDis(10, 20);
std::uniform_real_distribution<double> hitDis(0.0, 1.0);
int damage = damageDis(gen);
double hitChance = hitDis(gen);
if (hitChance < 0.2) { // 20%几率miss(远程更容易miss)
std::cout << " 💨 箭矢偏离目标!" << std::endl;
return 0;
} else {
std::cout << " ✅ 精准命中!造成 " << damage << " 点伤害" << std::endl;
}
target.takeDamage(damage);
return damage;
}
// 魔法攻击实现
int MagicAttack::executeAttack(GameCharacter& attacker, GameCharacter& target) {
std::cout << "🔮 " << attacker.getName() << " 吟唱魔法咒语!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> damageDis(20, 35);
std::uniform_real_distribution<double> hitDis(0.0, 1.0);
int damage = damageDis(gen);
double hitChance = hitDis(gen);
if (hitChance < 0.05) { // 5%几率失败
std::cout << " 💫 魔法施放失败!" << std::endl;
return 0;
} else if (hitChance > 0.85) { // 15%几率元素爆发
damage *= 1.5;
std::cout << " 🌟 元素爆发!造成 " << damage << " 点魔法伤害!" << std::endl;
} else {
std::cout << " ✨ 魔法命中!造成 " << damage << " 点伤害" << std::endl;
}
target.takeDamage(damage);
return damage;
}
// 偷袭实现
int SneakAttack::executeAttack(GameCharacter& attacker, GameCharacter& target) {
std::cout << "🗡️ " << attacker.getName() << " 悄悄接近目标..." << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> damageDis(5, 15);
std::uniform_real_distribution<double> critDis(0.0, 1.0);
int damage = damageDis(gen);
double critChance = critDis(gen);
if (critChance > 0.7) { // 30%几率致命一击
damage *= 3;
std::cout << " 💀 致命一击!造成 " << damage << " 点巨大伤害!" << std::endl;
} else if (critChance < 0.1) { // 10%几率被发现
std::cout << " 👀 被目标发现!偷袭失败" << std::endl;
return 0;
} else {
std::cout << " 🎯 偷袭成功!造成 " << damage << " 点伤害" << std::endl;
}
target.takeDamage(damage);
return damage;
}
// 战斗上下文实现
BattleContext::BattleContext(const std::string& characterName)
: m_character(characterName) {}
void BattleContext::setAttackStrategy(std::unique_ptr<AttackStrategy> strategy) {
m_attackStrategy = std::move(strategy);
}
void BattleContext::attack(GameCharacter& target) {
if (!m_attackStrategy) {
std::cout << "❌ " << m_character.getName() << " 没有设置攻击策略!" << std::endl;
return;
}
std::cout << "\n🎯 " << m_character.getName() << " 对 " << target.getName() << " 发动攻击" << std::endl;
std::cout << "攻击方式: " << m_attackStrategy->getName() << std::endl;
std::cout << "描述: " << m_attackStrategy->getDescription() << std::endl;
m_attackStrategy->executeAttack(m_character, target);
}
void BattleContext::displayStatus() const {
std::cout << "👤 " << m_character.getName()
<< " | 生命值: " << m_character.getHealth()
<< " | 攻击策略: " << getCurrentStrategy() << std::endl;
}
std::string BattleContext::getCurrentStrategy() const {
return m_attackStrategy ? m_attackStrategy->getName() : "无";
}
game_demo.cpp
cpp
/**
* @file game_demo.cpp
* @brief 游戏攻击策略演示
*/
#include "AttackStrategy.h"
#include <iostream>
#include <memory>
#include <vector>
/**
* @brief 模拟角色战斗
*/
void simulateBattle() {
std::cout << "⚔️ === 游戏战斗模拟 ===" << std::endl;
// 创建角色
BattleContext warrior("战士亚瑟");
BattleContext mage("法师梅林");
BattleContext archer("弓箭手罗宾");
BattleContext rogue("盗贼艾吉奥");
GameCharacter dragon("邪恶巨龙", 200);
std::cout << "\n🐉 出现强敌: " << dragon.getName()
<< " (生命值: " << dragon.getHealth() << ")" << std::endl;
// 设置各角色攻击策略
warrior.setAttackStrategy(std::make_unique<MeleeAttack>());
mage.setAttackStrategy(std::make_unique<MagicAttack>());
archer.setAttackStrategy(std::make_unique<RangedAttack>());
rogue.setAttackStrategy(std::make_unique<SneakAttack>());
// 显示角色状态
std::cout << "\n🎮 队伍状态:" << std::endl;
warrior.displayStatus();
mage.displayStatus();
archer.displayStatus();
rogue.displayStatus();
// 战斗回合
std::cout << "\n🔥 战斗开始!" << std::endl;
int round = 1;
while (dragon.getHealth() > 0) {
std::cout << "\n--- 第 " << round << " 回合 ---" << std::endl;
warrior.attack(dragon);
if (dragon.getHealth() <= 0) break;
mage.attack(dragon);
if (dragon.getHealth() <= 0) break;
archer.attack(dragon);
if (dragon.getHealth() <= 0) break;
rogue.attack(dragon);
if (dragon.getHealth() <= 0) break;
std::cout << "🐉 巨龙剩余生命值: " << dragon.getHealth() << std::endl;
round++;
if (round > 10) {
std::cout << "⏰ 战斗超时!" << std::endl;
break;
}
}
std::cout << "\n🎉 战斗结束!" << std::endl;
if (dragon.getHealth() <= 0) {
std::cout << "✅ 队伍击败了 " << dragon.getName() << "!" << std::endl;
} else {
std::cout << "❌ 队伍未能击败 " << dragon.getName() << std::endl;
}
}
/**
* @brief 演示策略动态切换
*/
void demonstrateStrategySwitching() {
std::cout << "\n🔄 === 策略动态切换演示 ===" << std::endl;
BattleContext hero("全能英雄");
GameCharacter goblin("哥布林", 50);
std::vector<std::unique_ptr<AttackStrategy>> strategies;
strategies.push_back(std::make_unique<MeleeAttack>());
strategies.push_back(std::make_unique<RangedAttack>());
strategies.push_back(std::make_unique<MagicAttack>());
strategies.push_back(std::make_unique<SneakAttack>());
std::cout << "🎯 英雄将尝试所有攻击方式:" << std::endl;
for (auto& strategy : strategies) {
hero.setAttackStrategy(std::move(strategy));
hero.attack(goblin);
std::cout << "哥布林剩余生命值: " << goblin.getHealth() << std::endl;
// 重置哥布林生命值
goblin = GameCharacter("哥布林", 50);
// 重新创建策略对象
if (strategy == nullptr) {
if (strategies[0] == nullptr) strategy = std::make_unique<MeleeAttack>();
else if (strategies[1] == nullptr) strategy = std::make_unique<RangedAttack>();
else if (strategies[2] == nullptr) strategy = std::make_unique<MagicAttack>();
else strategy = std::make_unique<SneakAttack>();
}
}
}
/**
* @brief 分析不同策略的伤害输出
*/
void analyzeDamageOutput() {
std::cout << "\n📊 === 攻击策略伤害分析 ===" << std::endl;
const int TEST_COUNT = 1000;
GameCharacter dummy("训练假人", 10000);
GameCharacter attacker("测试角色");
std::vector<std::unique_ptr<AttackStrategy>> strategies;
strategies.push_back(std::make_unique<MeleeAttack>());
strategies.push_back(std::make_unique<RangedAttack>());
strategies.push_back(std::make_unique<MagicAttack>());
strategies.push_back(std::make_unique<SneakAttack>());
std::vector<std::string> strategyNames = {"近战攻击", "远程攻击", "魔法攻击", "偷袭"};
for (size_t i = 0; i < strategies.size(); ++i) {
int totalDamage = 0;
int hitCount = 0;
int critCount = 0;
std::cout << "\n分析 " << strategyNames[i] << " (" << TEST_COUNT << "次攻击):" << std::endl;
for (int j = 0; j < TEST_COUNT; ++j) {
int damage = strategies[i]->executeAttack(attacker, dummy);
if (damage > 0) {
totalDamage += damage;
hitCount++;
}
}
double avgDamage = static_cast<double>(totalDamage) / TEST_COUNT;
double hitRate = (static_cast<double>(hitCount) / TEST_COUNT) * 100;
std::cout << "总伤害: " << totalDamage << std::endl;
std::cout << "平均每次攻击伤害: " << avgDamage << std::endl;
std::cout << "命中率: " << hitRate << "%" << std::endl;
}
}
int main() {
std::cout << "🎮 游戏攻击策略模式演示" << std::endl;
std::cout << "========================" << std::endl;
simulateBattle();
demonstrateStrategySwitching();
analyzeDamageOutput();
std::cout << "\n🏁 演示程序结束" << std::endl;
return 0;
}
战斗系统类图
GameCharacter -string m_name -int m_health +getName() : string +getHealth() : int +takeDamage(int damage) <<interface>> AttackStrategy +executeAttack(GameCharacter, GameCharacter) : int +getName() : string +getDescription() : string MeleeAttack +executeAttack(GameCharacter, GameCharacter) : int +getName() : string +getDescription() : string RangedAttack +executeAttack(GameCharacter, GameCharacter) : int +getName() : string +getDescription() : string MagicAttack +executeAttack(GameCharacter, GameCharacter) : int +getName() : string +getDescription() : string SneakAttack +executeAttack(GameCharacter, GameCharacter) : int +getName() : string +getDescription() : string BattleContext -GameCharacter m_character -unique_ptr<AttackStrategy> m_attackStrategy +setAttackStrategy(unique_ptr<AttackStrategy>) +attack(GameCharacter& target) +displayStatus()
Makefile完整版
makefile
# 编译器设置
CXX := g++
CXXFLAGS := -std=c++17 -Wall -Wextra -O2 -g
LDFLAGS := -lpthread
# 目标程序
TARGETS := sort_strategy_demo payment_demo game_demo
# 排序演示
SORT_SRCS := main.cpp SortStrategy.cpp
SORT_OBJS := $(SORT_SRCS:.cpp=.o)
# 支付演示
PAYMENT_SRCS := payment_demo.cpp PaymentStrategy.cpp
PAYMENT_OBJS := $(PAYMENT_SRCS:.cpp=.o)
# 游戏演示
GAME_SRCS := game_demo.cpp AttackStrategy.cpp
GAME_OBJS := $(GAME_SRCS:.cpp=.o)
# 头文件
HEADERS := SortStrategy.h PaymentStrategy.h AttackStrategy.h
# 默认编译所有目标
all: $(TARGETS)
# 排序演示目标
sort_strategy_demo: $(SORT_OBJS)
$(CXX) $(CXXFLAGS) -o $@ $(SORT_OBJS)
# 支付演示目标
payment_demo: $(PAYMENT_OBJS)
$(CXX) $(CXXFLAGS) -o $@ $(PAYMENT_OBJS) $(LDFLAGS)
# 游戏演示目标
game_demo: $(GAME_OBJS)
$(CXX) $(CXXFLAGS) -o $@ $(GAME_OBJS)
# 通用编译规则
%.o: %.cpp $(HEADERS)
$(CXX) $(CXXFLAGS) -c $< -o $@
# 清理规则
clean:
rm -f *.o $(TARGETS)
# 安装依赖检查
check-deps:
@echo "检查编译依赖..."
@which $(CXX) > /dev/null && echo "✅ g++ 编译器: 已安装" || echo "❌ g++ 编译器: 未安装"
@echo "C++ 标准: C++17"
@echo "所需头文件: <iostream>, <vector>, <memory>, <functional>, <random>, <chrono>, <thread>"
# 测试所有演示
test-all: all
@echo "测试排序演示..."
@./sort_strategy_demo > /dev/null && echo "✅ 排序演示: 通过" || echo "❌ 排序演示: 失败"
@echo "测试支付演示..."
@./payment_demo > /dev/null && echo "✅ 支付演示: 通过" || echo "❌ 支付演示: 失败"
@echo "测试游戏演示..."
@./game_demo > /dev/null && echo "✅ 游戏演示: 通过" || echo "❌ 游戏演示: 失败"
# 显示帮助信息
help:
@echo "可用目标:"
@echo " make all 编译所有演示程序"
@echo " make clean 清理所有编译结果"
@echo " make check-deps 检查编译依赖"
@echo " make test-all 编译并测试所有演示"
@echo " make help 显示此帮助信息"
@echo ""
@echo "单独编译:"
@echo " make sort_strategy_demo"
@echo " make payment_demo"
@echo " make game_demo"
.PHONY: all clean check-deps test-all help
4. 策略模式的高级应用与最佳实践
4.1 使用std::function的现代C++实现
除了传统的面向对象实现,现代C++更推荐使用std::function:
cpp
/**
* @brief 使用std::function的策略模式示例
*/
class ModernSorter {
public:
using SortAlgorithm = std::function<void(std::vector<int>&)>;
void setStrategy(SortAlgorithm algorithm) {
m_algorithm = std::move(algorithm);
}
void sort(std::vector<int>& data) {
if (m_algorithm) {
m_algorithm(data);
}
}
private:
SortAlgorithm m_algorithm;
};
// 使用lambda表达式作为策略
auto quickSort = [](std::vector<int>& data) {
std::sort(data.begin(), data.end());
};
auto reverseSort = [](std::vector<int>& data) {
std::sort(data.rbegin(), data.rend());
};
// 使用示例
ModernSorter sorter;
sorter.setStrategy(quickSort);
sorter.setStrategy([](std::vector<int>& data) {
// 自定义排序逻辑
std::sort(data.begin(), data.end(), std::greater<int>());
});
4.2 策略工厂模式结合
在实际项目中,策略模式常与工厂模式结合使用:
cpp
/**
* @brief 策略工厂类
*/
class StrategyFactory {
public:
static std::unique_ptr<PaymentStrategy> createPaymentStrategy(const std::string& type) {
if (type == "alipay") {
return std::make_unique<AlipayStrategy>();
} else if (type == "wechat") {
return std::make_unique<WechatPayStrategy>();
} else if (type == "creditcard") {
return std::make_unique<CreditCardStrategy>();
}
return nullptr;
}
static std::unique_ptr<AttackStrategy> createAttackStrategy(const std::string& type) {
// 类似的工厂方法...
return nullptr;
}
};
4.3 性能考量与优化
性能优化建议:
- 对于简单的策略,使用函数指针或std::function可能比虚函数调用更快
- 考虑使用模板策略在编译期确定算法
- 对于性能敏感的场景,避免频繁的策略切换
cpp
/**
* @brief 模板策略模式(编译期多态)
*/
template<typename Strategy>
class TemplateContext {
public:
void execute(const std::vector<int>& data) {
Strategy strategy;
strategy.process(data);
}
};
5. 总结
策略模式是C++开发中极其重要的设计模式,它通过将算法封装成独立的策略类,实现了算法的自由切换和扩展。通过本文的三个完整案例,我们展示了策略模式在不同场景下的应用:
- 排序算法:展示了算法策略的动态切换
- 支付系统:演示了业务逻辑策略的灵活配置
- 游戏战斗:体现了行为策略的多样性
核心价值:
- ✅ 符合开闭原则,易于扩展
- ✅ 消除复杂的条件判断
- ✅ 提高代码的可测试性
- ✅ 促进代码复用
适用场景:
- 一个系统需要在多种算法中选择一种
- 需要避免暴露复杂的、与算法相关的数据结构
- 一个类定义了多种行为,这些行为以多个条件语句的形式出现
策略模式与现代C++特性(如std::function、lambda表达式)结合,能够写出更加灵活、可维护的代码,是每个C++开发者必须掌握的重要设计模式。