当前位置: 首页 > news >正文

设计模式(C++)详解——策略模式(1)

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++中,策略模式有几种典型的实现方式:

// 方式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

/*** @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

/*** @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

/*** @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
# 编译器设置
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
操作说明

编译方法

# 确保系统已安装g++编译器(版本7.0或以上)
make clean && make

运行方式

./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

/*** @file PaymentStrategy.h* @brief 支付策略接口定义*/#ifndef PAYMENT_STRATEGY_H
#define PAYMENT_STRATEGY_H#include <iostream>
#include <memory>
#include <string>/*** @brief 支付请求结构体* * 包含支付所需的所有信息,传递给支付策略执行*/
struct PaymentRequest {std::string orderId;      ///< 订单IDdouble amount;           ///< 支付金额std::string currency;    ///< 货币类型std::string customerId;  ///< 客户IDPaymentRequest(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; ///< 交易IDstd::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

/*** @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));// 生成模拟交易IDstd::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));// 生成模拟交易IDstd::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

/*** @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;
}
支付流程时序图
客户端PaymentContextPaymentStrategy外部系统setStrategy(支付策略)executePayment(支付请求)pay(支付请求)策略特定处理调用支付网关API返回支付结果返回PaymentResult返回支付结果根据结果更新UI客户端PaymentContextPaymentStrategy外部系统
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) -lpthreadpayment_demo.o: payment_demo.cpp PaymentStrategy.h$(CXX) $(CXXFLAGS) -c payment_demo.cpp -o payment_demo.oPaymentStrategy.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)
操作说明

编译方法

make clean && make payment_demo

运行方式

./payment_demo

预期输出

💰 支付策略模式演示程序
=======================🛒 === 电商支付系统演示 ===📱 场景1: 客户选择支付宝支付💳 开始支付流程...
支付方式: 支付宝
🔵 支付宝支付处理中...订单: ORDER_2024_001金额: 299.99 CNY
支付结果: ✅ 成功
结果信息: 支付宝支付成功
交易ID: ALIPAY_ORDER_2024_001_1700000000🔄 === 动态策略切换演示 ===--- 处理订单 1 ---
💳 开始支付流程...
支付方式: 支付宝
🔵 支付宝支付处理中...
...📊 === 支付成功率分析 ===测试 支付宝 (100次):
成功次数: 89/100
成功率: 89%🎉 演示程序结束

3.3 案例三:游戏角色攻击策略

这个案例展示在游戏开发中如何使用策略模式实现不同的攻击行为。

完整代码实现

AttackStrategy.h

/*** @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

/*** @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%几率missstd::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

/*** @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完整版
# 编译器设置
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:

/*** @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 策略工厂模式结合

在实际项目中,策略模式常与工厂模式结合使用:

/*** @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 性能考量与优化

性能优化建议

  1. 对于简单的策略,使用函数指针或std::function可能比虚函数调用更快
  2. 考虑使用模板策略在编译期确定算法
  3. 对于性能敏感的场景,避免频繁的策略切换
/*** @brief 模板策略模式(编译期多态)*/
template<typename Strategy>
class TemplateContext {
public:void execute(const std::vector<int>& data) {Strategy strategy;strategy.process(data);}
};

5. 总结

策略模式是C++开发中极其重要的设计模式,它通过将算法封装成独立的策略类,实现了算法的自由切换和扩展。通过本文的三个完整案例,我们展示了策略模式在不同场景下的应用:

  1. 排序算法:展示了算法策略的动态切换
  2. 支付系统:演示了业务逻辑策略的灵活配置
  3. 游戏战斗:体现了行为策略的多样性

核心价值

  • ✅ 符合开闭原则,易于扩展
  • ✅ 消除复杂的条件判断
  • ✅ 提高代码的可测试性
  • ✅ 促进代码复用

适用场景

  • 一个系统需要在多种算法中选择一种
  • 需要避免暴露复杂的、与算法相关的数据结构
  • 一个类定义了多种行为,这些行为以多个条件语句的形式出现

策略模式与现代C++特性(如std::function、lambda表达式)结合,能够写出更加灵活、可维护的代码,是每个C++开发者必须掌握的重要设计模式。

http://www.dtcms.com/a/441798.html

相关文章:

  • 基于html5设计的网站建设做一些购物网站
  • Vivado综合通关指南:从IP打包失败到工具崩溃的四重考验
  • 语义分割概述
  • 数据结构之排序算法
  • 绍兴网站建设优化手机企业网站建设开发
  • 偏导数解释
  • Linux内核与设备管理:USB存储驱动usb_storage/uas的安全卸载与复原
  • fallocate: fallocate failed: Text file busy
  • visio实现扇形图绘制的方式方法-以三等分扇形为例
  • 以太坊私有链搭建与智能合约部署指南
  • 网站开发 教学大纲网页设计图片与图片的位置
  • python+flask_socketio+pyautogui实现简易远程桌面功能
  • flask_socketio+pyautogui实现的具有加密传输功能的极简远程桌面
  • 深入了解linux网络—— TCP网络通信(上)
  • Android Jetpack 核心组件实战:ViewModel + LiveData + DataBinding 详解
  • 商务厅网站建设意见怎么做网站注册推广
  • Fragment 崩溃恢复后出现重叠问题的复现方式
  • 设计模式(C++)详解——策略模式(2)
  • 使客户能够大规模交付生产就绪的人工智能代理
  • Layui 前端和 PHP 后端的大视频分片上传方案
  • 无状态HTTP的“记忆”方案:Spring Boot中CookieSession全栈实战
  • Java 内存模型(JMM)面试清单(含超通俗生活案例与深度理解)
  • 2015网站建设专业建网站设计公司
  • vue+springboot项目部署到服务器
  • QT肝8天17--优化用户管理
  • QT肝8天19--Windows程序部署
  • 【开题答辩过程】以《基于 Spring Boot 的宠物应急救援系统设计与实现》为例,不会开题答辩的可以进来看看
  • 成都seo网站建设沈阳网站建设推广服务
  • 网站栏目名短链接在线生成官网免费
  • Task Schemas: 基于前沿认知的复杂推理任务架构