第十四章:运筹帷幄,随机应变——Strategy的策略艺术
第十四章:运筹帷幄,随机应变——Strategy的策略艺术
风云再起,策略大师登场
在Observer展示完他那精妙的观察艺术后,Strategy身背多种兵器,从容不迫地走出。他的腰间挂满了各式各样的武器,每种武器都代表着不同的算法策略。
"Observer兄的通知机制确实精妙,"Strategy沉稳地说道,“但在算法选择和策略切换方面,需要更加灵活的应对方式。诸位请看——”
Strategy随手取下腰间的一柄长剑和一把短刀,在手中自如切换:“我的策略模式,专为解决算法族的定义和使用问题而生!我允许在运行时选择算法,让算法可以独立于使用它的客户端变化!”
架构老人眼中闪过赞许之色:“善!Strategy,就请你为大家展示这策略艺术的精妙所在。”
策略模式的核心要义
Strategy面向众人,开始阐述他的武学真谛:
“在我的策略模式中,主要包含三个核心角色:”
“Strategy(策略):定义所有支持的算法的公共接口。”
“ConcreteStrategy(具体策略):实现了策略接口的具体算法类。”
“Context(上下文):维护一个策略对象的引用,通过策略接口与之通信。”
"其精妙之处在于,"Strategy继续道,“客户端不需要知道具体算法的实现细节,只需要通过统一的策略接口来使用算法。这样,我们可以随时替换算法,而无需修改客户端的代码!”
C++实战:支付系统设计
"且让我以一个支付系统为例,展示策略模式的实战应用。"Strategy说着,手中凝聚出一道道代码流光。
基础框架搭建
首先,Strategy定义了支付策略接口:
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
#include <map>
#include <iomanip>
#include <sstream>
#include <random>
#include <thread>
#include <chrono>
#include <cmath>// 支付信息结构
struct PaymentInfo {double amount;std::string currency;std::string orderId;std::string customerId;std::chrono::system_clock::time_point timestamp;PaymentInfo(double amt, const std::string& curr = "USD", const std::string& order = "", const std::string& customer = ""): amount(amt), currency(curr), orderId(order), customerId(customer),timestamp(std::chrono::system_clock::now()) {}std::string toString() const {auto time = std::chrono::system_clock::to_time_t(timestamp);std::string timeStr = std::ctime(&time);timeStr.pop_back();std::stringstream ss;ss << "订单: " << orderId << " | 客户: " << customerId << " | 金额: " << std::fixed << std::setprecision(2) << amount << " " << currency<< " | 时间: " << timeStr;return ss.str();}
};// 支付结果结构
struct PaymentResult {bool success;std::string transactionId;std::string message;double fee;double finalAmount;PaymentResult(bool s, const std::string& tid = "", const std::string& msg = "", double f = 0.0, double final = 0.0): success(s), transactionId(tid), message(msg), fee(f), finalAmount(final) {}std::string toString() const {std::stringstream ss;ss << (success ? "✅" : "❌") << " " << message;if (success) {ss << " | 交易ID: " << transactionId << " | 手续费: " << std::fixed << std::setprecision(2) << fee<< " | 实收: " << finalAmount;}return ss.str();}
};// 策略接口:支付策略
class PaymentStrategy {
public:virtual ~PaymentStrategy() = default;virtual PaymentResult processPayment(const PaymentInfo& paymentInfo) = 0;virtual std::string getStrategyName() const = 0;virtual double calculateFee(double amount) const = 0;virtual bool validatePayment(const PaymentInfo& paymentInfo) const = 0;
};
具体策略实现
Strategy展示了多种支付方式的具体实现:
// 具体策略:信用卡支付
class CreditCardPayment : public PaymentStrategy {
private:std::string processorName_;double feeRate_;public:CreditCardPayment(const std::string& processor = "Stripe", double feeRate = 0.029): processorName_(processor), feeRate_(feeRate) {std::cout << "💳 创建信用卡支付策略: " << processorName_ << std::endl;}PaymentResult processPayment(const PaymentInfo& paymentInfo) override {std::cout << "🔒 使用 " << processorName_ << " 处理信用卡支付..." << std::endl;// 模拟处理时间std::this_thread::sleep_for(std::chrono::milliseconds(800));if (!validatePayment(paymentInfo)) {return PaymentResult(false, "", "信用卡支付验证失败");}double fee = calculateFee(paymentInfo.amount);double finalAmount = paymentInfo.amount - fee;// 生成交易IDstd::string transactionId = "CC_" + std::to_string(rand() % 1000000);std::cout << "✅ 信用卡支付成功!" << std::endl;return PaymentResult(true, transactionId, "信用卡支付成功 - " + processorName_, fee, finalAmount);}std::string getStrategyName() const override {return "信用卡支付 (" + processorName_ + ")";}double calculateFee(double amount) const override {return amount * feeRate_ + 0.30; // 固定费用 + 百分比}bool validatePayment(const PaymentInfo& paymentInfo) const override {if (paymentInfo.amount <= 0) {std::cout << "❌ 金额必须大于0" << std::endl;return false;}if (paymentInfo.amount > 10000.0) {std::cout << "❌ 单笔支付金额不能超过10000" << std::endl;return false;}return true;}void setFeeRate(double rate) {feeRate_ = rate;std::cout << "💰 设置信用卡费率: " << rate * 100 << "%" << std::endl;}
};// 具体策略:PayPal支付
class PayPalPayment : public PaymentStrategy {
private:std::string email_;double feeRate_;public:PayPalPayment(const std::string& email = "merchant@example.com", double feeRate = 0.024): email_(email), feeRate_(feeRate) {std::cout << "🔵 创建PayPal支付策略: " << email_ << std::endl;}PaymentResult processPayment(const PaymentInfo& paymentInfo) override {std::cout << "🌐 通过PayPal处理支付..." << std::endl;// 模拟网络请求时间std::this_thread::sleep_for(std::chrono::milliseconds(1200));if (!validatePayment(paymentInfo)) {return PaymentResult(false, "", "PayPal支付验证失败");}double fee = calculateFee(paymentInfo.amount);double finalAmount = paymentInfo.amount - fee;// 生成交易IDstd::string transactionId = "PP_" + std::to_string(rand() % 1000000);std::cout << "✅ PayPal支付成功!" << std::endl;return PaymentResult(true, transactionId, "PayPal支付成功", fee, finalAmount);}std::string getStrategyName() const override {return "PayPal支付 (" + email_ + ")";}double calculateFee(double amount) const override {return amount * feeRate_;}bool validatePayment(const PaymentInfo& paymentInfo) const override {if (paymentInfo.amount < 1.0) {std::cout << "❌ PayPal支付金额不能少于1元" << std::endl;return false;}return true;}
};// 具体策略:加密货币支付
class CryptoPayment : public PaymentStrategy {
private:std::string cryptocurrency_;double networkFee_;public:CryptoPayment(const std::string& crypto = "Bitcoin", double networkFee = 2.0): cryptocurrency_(crypto), networkFee_(networkFee) {std::cout << "₿ 创建加密货币支付策略: " << cryptocurrency_ << std::endl;}PaymentResult processPayment(const PaymentInfo& paymentInfo) override {std::cout << "⛓️ 处理 " << cryptocurrency_ << " 支付..." << std::endl;// 模拟区块链确认时间std::this_thread::sleep_for(std::chrono::milliseconds(2000));if (!validatePayment(paymentInfo)) {return PaymentResult(false, "", "加密货币支付验证失败");}double fee = calculateFee(paymentInfo.amount);double finalAmount = paymentInfo.amount - fee;// 生成交易哈希std::string transactionId = crypto_ + "_" + generateTransactionHash();std::cout << "✅ " << cryptocurrency_ << " 支付成功!" << std::endl;return PaymentResult(true, transactionId, cryptocurrency_ + " 支付成功", fee, finalAmount);}std::string getStrategyName() const override {return cryptocurrency_ + " 支付";}double calculateFee(double amount) const override {return networkFee_; // 固定网络费用}bool validatePayment(const PaymentInfo& paymentInfo) const override {if (paymentInfo.amount <= 0) {std::cout << "❌ 金额必须大于0" << std::endl;return false;}return true;}private:std::string generateTransactionHash() const {const char chars[] = "0123456789abcdef";std::string hash;for (int i = 0; i < 64; ++i) {hash += chars[rand() % 16];}return hash;}std::string crypto_ = "BTC"; // 简化表示
};// 具体策略:银行转账
class BankTransferPayment : public PaymentStrategy {
private:std::string bankName_;double fixedFee_;public:BankTransferPayment(const std::string& bank = "中国银行", double fixedFee = 1.5): bankName_(bank), fixedFee_(fixedFee) {std::cout << "🏦 创建银行转账策略: " << bankName_ << std::endl;}PaymentResult processPayment(const PaymentInfo& paymentInfo) override {std::cout << "💼 处理 " << bankName_ << " 银行转账..." << std::endl;// 模拟银行处理时间std::this_thread::sleep_for(std::chrono::milliseconds(1500));if (!validatePayment(paymentInfo)) {return PaymentResult(false, "", "银行转账验证失败");}double fee = calculateFee(paymentInfo.amount);double finalAmount = paymentInfo.amount - fee;// 生成交易IDstd::string transactionId = "BT_" + std::to_string(rand() % 1000000);std::cout << "✅ 银行转账成功!" << std::endl;return PaymentResult(true, transactionId, bankName_ + " 银行转账成功", fee, finalAmount);}std::string getStrategyName() const override {return bankName_ + " 银行转账";}double calculateFee(double amount) const override {return fixedFee_; // 固定手续费}bool validatePayment(const PaymentInfo& paymentInfo) const override {if (paymentInfo.amount < 10.0) {std::cout << "❌ 银行转账金额不能少于10元" << std::endl;return false;}if (paymentInfo.amount > 50000.0) {std::cout << "❌ 单笔银行转账不能超过50000元" << std::endl;return false;}return true;}
};
上下文实现
Strategy创建了支付处理器上下文:
// 上下文:支付处理器
class PaymentProcessor {
private:std::unique_ptr<PaymentStrategy> strategy_;std::string processorName_;std::vector<PaymentResult> paymentHistory_;public:PaymentProcessor(const std::string& name = "通用支付处理器") : processorName_(name) {std::cout << "🔄 创建支付处理器: " << processorName_ << std::endl;}~PaymentProcessor() {std::cout << "🗑️ 销毁支付处理器: " << processorName_ << std::endl;}void setStrategy(std::unique_ptr<PaymentStrategy> strategy) {strategy_ = std::move(strategy);std::cout << "🎯 " << processorName_ << " 设置策略: " << strategy_->getStrategyName() << std::endl;}PaymentResult processPayment(const PaymentInfo& paymentInfo) {if (!strategy_) {std::cout << "❌ 未设置支付策略!" << std::endl;return PaymentResult(false, "", "未设置支付策略");}std::cout << "\n💸 " << processorName_ << " 开始处理支付..." << std::endl;std::cout << "📄 " << paymentInfo.toString() << std::endl;auto startTime = std::chrono::high_resolution_clock::now();PaymentResult result = strategy_->processPayment(paymentInfo);auto endTime = std::chrono::high_resolution_clock::now();auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);std::cout << "⏱️ 处理耗时: " << duration.count() << "ms" << std::endl;// 记录支付历史paymentHistory_.push_back(result);std::cout << "📊 支付结果: " << result.toString() << std::endl;return result;}std::string getCurrentStrategyName() const {return strategy_ ? strategy_->getStrategyName() : "未设置策略";}void showPaymentHistory() const {std::cout << "\n📜 " << processorName_ << " 支付历史 (" << paymentHistory_.size() << " 笔):" << std::endl;int successCount = 0;double totalAmount = 0.0;double totalFees = 0.0;for (size_t i = 0; i < paymentHistory_.size(); ++i) {const auto& result = paymentHistory_[i];std::cout << " " << (i + 1) << ". " << result.toString() << std::endl;if (result.success) {successCount++;totalAmount += result.finalAmount;totalFees += result.fee;}}std::cout << "\n📈 统计摘要:" << std::endl;std::cout << " 成功交易: " << successCount << "/" << paymentHistory_.size() << std::endl;std::cout << " 总实收金额: $" << std::fixed << std::setprecision(2) << totalAmount << std::endl;std::cout << " 总手续费: $" << totalFees << std::endl;if (successCount > 0) {std::cout << " 平均手续费率: " << std::fixed << std::setprecision(2) << (totalFees / (totalAmount + totalFees) * 100) << "%" << std::endl;}}void clearHistory() {paymentHistory_.clear();std::cout << "🧹 清空支付历史" << std::endl;}std::string getProcessorInfo() const {std::stringstream ss;ss << processorName_ << " [策略: " << getCurrentStrategyName() << ", 历史记录: " << paymentHistory_.size() << " 笔]";return ss.str();}
};
UML 武功秘籍图
实战演练:高级策略系统
Strategy继续展示更复杂的策略模式应用:
// 策略工厂:创建各种支付策略
class PaymentStrategyFactory {
public:static std::unique_ptr<PaymentStrategy> createCreditCardStrategy(const std::string& processor = "Stripe", double feeRate = 0.029) {return std::make_unique<CreditCardPayment>(processor, feeRate);}static std::unique_ptr<PaymentStrategy> createPayPalStrategy(const std::string& email = "merchant@example.com", double feeRate = 0.024) {return std::make_unique<PayPalPayment>(email, feeRate);}static std::unique_ptr<PaymentStrategy> createCryptoStrategy(const std::string& crypto = "Bitcoin", double networkFee = 2.0) {return std::make_unique<CryptoPayment>(crypto, networkFee);}static std::unique_ptr<PaymentStrategy> createBankTransferStrategy(const std::string& bank = "中国银行", double fixedFee = 1.5) {return std::make_unique<BankTransferPayment>(bank, fixedFee);}static std::unique_ptr<PaymentStrategy> createStrategyFromConfig(const std::string& strategyType, const std::map<std::string, std::string>& config) {if (strategyType == "credit_card") {std::string processor = config.count("processor") ? config.at("processor") : "Stripe";double feeRate = config.count("fee_rate") ? std::stod(config.at("fee_rate")) : 0.029;return createCreditCardStrategy(processor, feeRate);}else if (strategyType == "paypal") {std::string email = config.count("email") ? config.at("email") : "merchant@example.com";double feeRate = config.count("fee_rate") ? std::stod(config.at("fee_rate")) : 0.024;return createPayPalStrategy(email, feeRate);}else if (strategyType == "crypto") {std::string crypto = config.count("crypto") ? config.at("crypto") : "Bitcoin";double networkFee = config.count("network_fee") ? std::stod(config.at("network_fee")) : 2.0;return createCryptoStrategy(crypto, networkFee);}else if (strategyType == "bank_transfer") {std::string bank = config.count("bank") ? config.at("bank") : "中国银行";double fixedFee = config.count("fixed_fee") ? std::stod(config.at("fixed_fee")) : 1.5;return createBankTransferStrategy(bank, fixedFee);}throw std::invalid_argument("未知的策略类型: " + strategyType);}
};// 策略管理器:管理多个策略和上下文
class StrategyManager {
private:std::map<std::string, std::unique_ptr<PaymentProcessor>> processors_;std::map<std::string, std::unique_ptr<PaymentStrategy>> availableStrategies_;public:StrategyManager() {std::cout << "👨💼 创建策略管理器" << std::endl;initializeDefaultStrategies();}~StrategyManager() {std::cout << "🗑️ 销毁策略管理器" << std::endl;}void initializeDefaultStrategies() {// 初始化可用的策略availableStrategies_["credit_card_stripe"] = PaymentStrategyFactory::createCreditCardStrategy("Stripe", 0.029);availableStrategies_["credit_card_paypal"] = PaymentStrategyFactory::createCreditCardStrategy("PayPal", 0.034);availableStrategies_["paypal"] = PaymentStrategyFactory::createPayPalStrategy("merchant@example.com", 0.024);availableStrategies_["bitcoin"] = PaymentStrategyFactory::createCryptoStrategy("Bitcoin", 2.0);availableStrategies_["ethereum"] = PaymentStrategyFactory::createCryptoStrategy("Ethereum", 1.5);availableStrategies_["bank_transfer"] = PaymentStrategyFactory::createBankTransferStrategy("中国银行", 1.5);std::cout << "✅ 初始化 " << availableStrategies_.size() << " 个默认策略" << std::endl;}void createProcessor(const std::string& processorName) {processors_[processorName] = std::make_unique<PaymentProcessor>(processorName);std::cout << "🆕 创建支付处理器: " << processorName << std::endl;}void setProcessorStrategy(const std::string& processorName, const std::string& strategyKey) {auto processorIt = processors_.find(processorName);auto strategyIt = availableStrategies_.find(strategyKey);if (processorIt != processors_.end() && strategyIt != availableStrategies_.end()) {// 克隆策略(因为同一个策略可能被多个处理器使用)auto clonedStrategy = cloneStrategy(strategyKey);processorIt->second->setStrategy(std::move(clonedStrategy));} else {std::cout << "❌ 找不到处理器或策略: " << processorName << "/" << strategyKey << std::endl;}}void addCustomStrategy(const std::string& key, std::unique_ptr<PaymentStrategy> strategy) {availableStrategies_[key] = std::move(strategy);std::cout << "🆕 添加自定义策略: " << key << std::endl;}PaymentResult processPaymentWith(const std::string& processorName, const PaymentInfo& paymentInfo) {auto it = processors_.find(processorName);if (it != processors_.end()) {return it->second->processPayment(paymentInfo);}return PaymentResult(false, "", "找不到处理器: " + processorName);}void listAllProcessors() const {std::cout << "\n📋 所有支付处理器 (" << processors_.size() << " 个):" << std::endl;for (const auto& pair : processors_) {std::cout << " • " << pair.second->getProcessorInfo() << std::endl;}}void listAllStrategies() const {std::cout << "\n🎯 所有可用策略 (" << availableStrategies_.size() << " 个):" << std::endl;for (const auto& pair : availableStrategies_) {std::cout << " • " << pair.first << ": " << pair.second->getStrategyName() << std::endl;}}void showProcessorHistory(const std::string& processorName) const {auto it = processors_.find(processorName);if (it != processors_.end()) {it->second->showPaymentHistory();} else {std::cout << "❌ 找不到处理器: " << processorName << std::endl;}}private:std::unique_ptr<PaymentStrategy> cloneStrategy(const std::string& strategyKey) const {auto it = availableStrategies_.find(strategyKey);if (it != availableStrategies_.end()) {// 根据策略类型创建新的实例if (auto creditCard = dynamic_cast<CreditCardPayment*>(it->second.get())) {return std::make_unique<CreditCardPayment>(*creditCard);}else if (auto paypal = dynamic_cast<PayPalPayment*>(it->second.get())) {return std::make_unique<PayPalPayment>(*paypal);}else if (auto crypto = dynamic_cast<CryptoPayment*>(it->second.get())) {return std::make_unique<CryptoPayment>(*crypto);}else if (auto bank = dynamic_cast<BankTransferPayment*>(it->second.get())) {return std::make_unique<BankTransferPayment>(*bank);}}return nullptr;}
};
策略模式的招式解析
招式一:动态策略选择
// 智能策略选择器:根据条件自动选择最佳策略
class SmartStrategySelector {
public:static std::string selectBestStrategy(double amount, const std::string& currency, const std::string& customerRegion) {std::cout << "\n🤔 智能选择策略..." << std::endl;std::cout << " 金额: " << amount << " " << currency << std::endl;std::cout << " 客户地区: " << customerRegion << std::endl;// 基于规则的策略选择if (amount < 1.0) {std::cout << " 💡 推荐: PayPal (小额支付)" << std::endl;return "paypal";}else if (amount > 10000.0) {std::cout << " 💡 推荐: 银行转账 (大额支付)" << std::endl;return "bank_transfer";}else if (customerRegion == "国际" || customerRegion == "海外") {std::cout << " 💡 推荐: 加密货币 (国际支付)" << std::endl;return "bitcoin";}else if (amount <= 1000.0) {std::cout << " 💡 推荐: Stripe信用卡 (常规支付)" << std::endl;return "credit_card_stripe";}else {std::cout << " 💡 推荐: PayPal信用卡 (中等金额)" << std::endl;return "credit_card_paypal";}}static double calculateOptimalFee(double amount, const std::string& strategyKey) {// 创建临时策略来计算费用auto tempStrategy = PaymentStrategyFactory::createStrategyFromConfig(strategyKey, {});return tempStrategy->calculateFee(amount);}
};// 自适应支付处理器
class AdaptivePaymentProcessor {
private:StrategyManager& strategyManager_;std::string processorName_;public:AdaptivePaymentProcessor(StrategyManager& manager, const std::string& name): strategyManager_(manager), processorName_(name) {std::cout << "🧠 创建自适应支付处理器: " << processorName_ << std::endl;}PaymentResult processPaymentAdaptive(const PaymentInfo& paymentInfo) {std::cout << "\n🎯 " << processorName_ << " 开始自适应支付处理..." << std::endl;// 智能选择最佳策略std::string bestStrategy = SmartStrategySelector::selectBestStrategy(paymentInfo.amount, paymentInfo.currency, "国内"); //