策略模式(Strategy Pattern)是行为型设计模式中的算法封装大师,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户端,实现了算法与客户端的解耦。本文将深入探索策略模式的核心思想、实现技巧以及在C++中的高效实践。


为什么需要策略模式?

在软件开发中,算法选择是常见需求:

  • 支付系统的多种支付方式(信用卡、PayPal、加密货币)

  • 导航系统的不同路径规划(最快、最短、避开高速)

  • 数据压缩的不同算法(ZIP、RAR、7z)

  • 排序算法的动态选择(快速排序、归并排序、堆排序)

  • 渲染引擎的不同渲染策略(光线追踪、光栅化)

硬编码算法选择会导致:
条件爆炸:复杂的if-else或switch-case语句
维护困难:添加新算法需修改现有代码
紧耦合:业务逻辑与算法实现混杂
复用性差:算法难以单独复用

策略模式通过封装算法族解决了这些问题。


策略模式的核心概念

模式结构解析
[上下文] → [策略接口]  
              ▲  
              |  
   [具体策略A]   [具体策略B]
关键角色定义
  1. 上下文(Context)

    • 维护策略对象的引用

    • 提供设置策略的接口

    • 将请求委托给当前策略对象

  2. 策略接口(Strategy)

    • 定义算法族的公共接口

    • 声明算法执行方法

  3. 具体策略(Concrete Strategy)

    • 实现策略接口

    • 封装具体算法实现


C++实现:电商支付处理系统

实现支持多种支付方式且可扩展的支付系统:

#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <stdexcept>
#include <ctime>
#include <iomanip>
#include <cmath>

// ================= 支付策略接口 =================
class PaymentStrategy {
public:
    virtual ~PaymentStrategy() = default;
    virtual bool processPayment(double amount) = 0;
    virtual std::string getStrategyName() const = 0;
    virtual void displayDetails() const = 0;
};

// ================= 具体策略:信用卡支付 =================
class CreditCardPayment : public PaymentStrategy {
public:
    CreditCardPayment(const std::string& cardNumber, 
                      const std::string& expiryDate,
                      const std::string& cvv)
        : cardNumber_(maskCardNumber(cardNumber)),
          expiryDate_(expiryDate),
          cvv_(cvv) {}
    
    bool processPayment(double amount) override {
        std::cout << "处理信用卡支付..." << std::endl;
        std::cout << "验证卡信息: " << cardNumber_ << " 有效期: " << expiryDate_ << std::endl;
        
        // 模拟支付处理
        std::cout << "向银行发送支付请求: ¥" << amount << std::endl;
        simulateNetworkDelay();
        
        // 模拟90%成功率
        if (rand() % 100 < 90) {
            std::cout << "信用卡支付成功!\n";
            return true;
        }
        
        std::cout << "信用卡支付失败: 银行拒绝交易\n";
        return false;
    }
    
    std::string getStrategyName() const override {
        return "信用卡支付";
    }
    
    void displayDetails() const override {
        std::cout << "信用卡: " << cardNumber_ 
                  << " 有效期: " << expiryDate_ << std::endl;
    }

private:
    static std::string maskCardNumber(const std::string& cardNumber) {
        if (cardNumber.length() < 12) return "****-****-****-****";
        return "****-****-****-" + cardNumber.substr(cardNumber.length() - 4);
    }
    
    void simulateNetworkDelay() {
        std::cout << "与银行通信中...";
        for (int i = 0; i < 3; ++i) {
            std::cout << "." << std::flush;
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
        std::cout << std::endl;
    }
    
    std::string cardNumber_;
    std::string expiryDate_;
    std::string cvv_;
};

// ================= 具体策略:PayPal支付 =================
class PayPalPayment : public PaymentStrategy {
public:
    explicit PayPalPayment(const std::string& email) 
        : email_(email) {}
    
    bool processPayment(double amount) override {
        std::cout << "处理PayPal支付..." << std::endl;
        std::cout << "账户: " << email_ << std::endl;
        
        // 模拟支付处理
        std::cout << "重定向到PayPal登录页面" << std::endl;
        simulateUserInteraction();
        
        // 模拟85%成功率
        if (rand() % 100 < 85) {
            std::cout << "PayPal支付成功!\n";
            return true;
        }
        
        std::cout << "PayPal支付失败: 用户取消\n";
        return false;
    }
    
    std::string getStrategyName() const override {
        return "PayPal支付";
    }
    
    void displayDetails() const override {
        std::cout << "PayPal账户: " << email_ << std::endl;
    }

private:
    void simulateUserInteraction() {
        std::cout << "用户登录中...";
        for (int i = 0; i < 5; ++i) {
            std::cout << "." << std::flush;
            std::this_thread::sleep_for(std::chrono::milliseconds(300));
        }
        std::cout << "\n用户确认支付 ¥" << std::fixed << std::setprecision(2) 
                  << amount_ << std::endl;
    }
    
    std::string email_;
    double amount_ = 0.0;
};

// ================= 具体策略:加密货币支付 =================
class CryptoPayment : public PaymentStrategy {
public:
    CryptoPayment(const std::string& walletAddress, 
                  const std::string& currency = "BTC")
        : walletAddress_(walletAddress),
          currency_(currency) {}
    
    bool processPayment(double amount) override {
        std::cout << "处理加密货币支付..." << std::endl;
        std::cout << "钱包地址: " << walletAddress_ << std::endl;
        
        // 转换为加密货币
        double cryptoAmount = convertToCrypto(amount);
        std::cout << "转换金额: ¥" << amount << " → " 
                  << cryptoAmount << " " << currency_ << std::endl;
        
        // 模拟区块链交易
        simulateBlockchainTransaction();
        
        // 模拟75%成功率
        if (rand() % 100 < 75) {
            std::cout << "加密货币支付成功!\n";
            return true;
        }
        
        std::cout << "加密货币支付失败: 交易超时\n";
        return false;
    }
    
    std::string getStrategyName() const override {
        return currency_ + "支付";
    }
    
    void displayDetails() const override {
        std::cout << currency_ << "钱包: " << walletAddress_ << std::endl;
    }

private:
    double convertToCrypto(double amount) {
        // 模拟汇率转换
        double exchangeRate = 0.000025; // 1 CNY = 0.000025 BTC
        if (currency_ == "ETH") exchangeRate = 0.00038;
        else if (currency_ == "LTC") exchangeRate = 0.0032;
        
        return amount * exchangeRate;
    }
    
    void simulateBlockchainTransaction() {
        std::cout << "等待区块链确认...\n";
        for (int i = 0; i < 6; ++i) {
            std::cout << "区块" << (i+1) << "/6 确认中..." << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(700));
        }
    }
    
    std::string walletAddress_;
    std::string currency_;
};

// ================= 上下文:订单处理器 =================
class OrderProcessor {
public:
    explicit OrderProcessor(double amount) : amount_(amount) {}
    
    void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strategy) {
        strategy_ = std::move(strategy);
        std::cout << "支付方式设置为: " << strategy_->getStrategyName() << std::endl;
    }
    
    bool processOrder() {
        if (!strategy_) {
            throw std::runtime_error("未设置支付策略");
        }
        
        std::cout << "\n===== 处理订单 =====" << std::endl;
        std::cout << "订单金额: ¥" << std::fixed << std::setprecision(2) << amount_ << std::endl;
        strategy_->displayDetails();
        
        return strategy_->processPayment(amount_);
    }
    
    void addDiscount(double discount) {
        amount_ -= discount;
        std::cout << "应用折扣: ¥" << discount << " | 新金额: ¥" << amount_ << std::endl;
    }
    
    void addTax(double taxRate) {
        double tax = amount_ * taxRate;
        amount_ += tax;
        std::cout << "添加税费: ¥" << tax << " | 新金额: ¥" << amount_ << std::endl;
    }

private:
    double amount_;
    std::unique_ptr<PaymentStrategy> strategy_;
};

// ================= 策略工厂 =================
class PaymentStrategyFactory {
public:
    static std::unique_ptr<PaymentStrategy> createStrategy(
        const std::string& type, 
        const std::map<std::string, std::string>& params) {
        
        if (type == "credit_card") {
            return std::make_unique<CreditCardPayment>(
                params.at("card_number"),
                params.at("expiry_date"),
                params.at("cvv"));
        }
        else if (type == "paypal") {
            return std::make_unique<PayPalPayment>(params.at("email"));
        }
        else if (type == "crypto") {
            return std::make_unique<CryptoPayment>(
                params.at("wallet_address"),
                params.value("currency", "BTC"));
        }
        
        throw std::invalid_argument("未知支付类型: " + type);
    }
};

// ================= 客户端代码 =================
int main() {
    srand(time(nullptr)); // 初始化随机种子
    
    // 创建订单
    OrderProcessor order(999.99);
    order.addDiscount(100.0); // 满减折扣
    order.addTax(0.08);       // 8%税费
    
    // 用户选择支付方式
    int choice;
    std::cout << "请选择支付方式:\n"
              << "1. 信用卡支付\n"
              << "2. PayPal支付\n"
              << "3. 加密货币支付\n"
              << "输入选择: ";
    std::cin >> choice;
    
    // 根据选择设置策略
    std::map<std::string, std::string> params;
    switch (choice) {
        case 1: {
            std::string card, expiry, cvv;
            std::cout << "输入信用卡号: ";
            std::cin >> card;
            std::cout << "输入有效期 (MM/YY): ";
            std::cin >> expiry;
            std::cout << "输入CVV: ";
            std::cin >> cvv;
            
            params = {{"card_number", card}, {"expiry_date", expiry}, {"cvv", cvv}};
            order.setPaymentStrategy(
                PaymentStrategyFactory::createStrategy("credit_card", params));
            break;
        }
        case 2: {
            std::string email;
            std::cout << "输入PayPal邮箱: ";
            std::cin >> email;
            
            params = {{"email", email}};
            order.setPaymentStrategy(
                PaymentStrategyFactory::createStrategy("paypal", params));
            break;
        }
        case 3: {
            std::string wallet, currency;
            std::cout << "输入钱包地址: ";
            std::cin >> wallet;
            std::cout << "输入加密货币类型 (BTC/ETH/LTC, 默认为BTC): ";
            std::cin >> currency;
            
            params = {{"wallet_address", wallet}};
            if (!currency.empty()) params["currency"] = currency;
            order.setPaymentStrategy(
                PaymentStrategyFactory::createStrategy("crypto", params));
            break;
        }
        default:
            std::cerr << "无效选择!" << std::endl;
            return 1;
    }
    
    // 处理订单
    bool success = order.processOrder();
    
    // 处理结果
    if (success) {
        std::cout << "\n 订单处理成功! 感谢您的购买。\n";
    } else {
        std::cout << "\n 订单处理失败! 请尝试其他支付方式。\n";
        
        // 策略切换示例
        std::cout << "尝试使用PayPal支付...\n";
        std::string email = "customer@example.com";
        order.setPaymentStrategy(std::make_unique<PayPalPayment>(email));
        success = order.processOrder();
        
        if (success) {
            std::cout << "\n 使用PayPal支付成功!\n";
        }
    }
    
    return 0;
}

策略模式的五大优势

  1. 算法封装

    // 每个算法独立封装
    class QuickSort : public SortStrategy {
        void sort(DataSet& data) override {
            // 快速排序实现
        }
    };
  2. 运行时切换

    // 动态改变策略
    context.setStrategy(new PayPalStrategy());
  3. 消除条件语句

    // 代替switch-case
    paymentStrategy->process(amount);
  4. 开放封闭原则

    // 添加新策略不影响现有代码
    class CryptoStrategy : public PaymentStrategy {
        // 新支付算法
    };
  5. 算法复用

    // 相同策略可用于不同上下文
    orderProcessor.setStrategy(creditCardStrategy);
    donationProcessor.setStrategy(creditCardStrategy);

策略模式的高级应用

1. 策略组合
class CompositeStrategy : public PaymentStrategy {
public:
    void addStrategy(std::unique_ptr<PaymentStrategy> strategy) {
        strategies_.push_back(std::move(strategy));
    }
    
    bool processPayment(double amount) override {
        double remaining = amount;
        for (auto& strategy : strategies_) {
            double partial = std::min(remaining, maxAmountFor(strategy));
            if (!strategy->processPayment(partial)) return false;
            remaining -= partial;
            if (remaining <= 0) break;
        }
        return true;
    }

private:
    std::vector<std::unique_ptr<PaymentStrategy>> strategies_;
};

// 使用
auto composite = std::make_unique<CompositeStrategy>();
composite->addStrategy(std::make_unique<CreditCardPayment>(...));
composite->addStrategy(std::make_unique<PayPalPayment>(...));
order.setPaymentStrategy(std::move(composite));
2. 策略自动选择
class SmartPaymentSelector {
public:
    void processPayment(double amount) {
        auto strategy = selectBestStrategy(amount);
        strategy->processPayment(amount);
    }
    
private:
    std::unique_ptr<PaymentStrategy> selectBestStrategy(double amount) {
        // 基于规则选择最佳策略
        if (amount > 5000) return std::make_unique<BankTransferStrategy>();
        if (user.hasCryptoPreference()) return std::make_unique<CryptoPayment>();
        return std::make_unique<CreditCardPayment>();
    }
};
3. 策略性能分析
class ProfiledStrategy : public PaymentStrategy {
public:
    explicit ProfiledStrategy(std::unique_ptr<PaymentStrategy> strategy)
        : wrapped_(std::move(strategy)) {}
    
    bool processPayment(double amount) override {
        auto start = std::chrono::high_resolution_clock::now();
        bool result = wrapped_->processPayment(amount);
        auto end = std::chrono::high_resolution_clock::now();
        
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << wrapped_->getStrategyName() << " 耗时: " 
                  << duration.count() << "ms" << std::endl;
        
        return result;
    }

private:
    std::unique_ptr<PaymentStrategy> wrapped_;
};

// 使用
auto baseStrategy = std::make_unique<CreditCardPayment>(...);
order.setPaymentStrategy(std::make_unique<ProfiledStrategy>(std::move(baseStrategy)));

策略模式的应用场景

1. 导航系统
class NavigationContext {
public:
    void setStrategy(std::unique_ptr<RoutingStrategy> strategy) {
        strategy_ = std::move(strategy));
    }
    
    Route calculateRoute(Point start, Point end) {
        return strategy_->calculateRoute(start, end);
    }

private:
    std::unique_ptr<RoutingStrategy> strategy_;
};

class FastestRouteStrategy : public RoutingStrategy {
    Route calculateRoute(Point start, Point end) override {
        // 使用实时交通数据
        return calculateFastestRoute(start, end);
    }
};

class ScenicRouteStrategy : public RoutingStrategy {
    Route calculateRoute(Point start, Point end) override {
        // 选择风景优美的路线
        return calculateScenicRoute(start, end);
    }
};
2. 数据压缩工具
class CompressionContext {
public:
    void setCompressionStrategy(std::unique_ptr<CompressionStrategy> strategy) {
        strategy_ = std::move(strategy));
    }
    
    void compressFile(const std::string& filename) {
        strategy_->compress(filename);
    }

private:
    std::unique_ptr<CompressionStrategy> strategy_;
};

class ZipCompression : public CompressionStrategy {
    void compress(const std::string& filename) override {
        // ZIP压缩实现
        std::cout << "使用ZIP算法压缩: " << filename << std::endl;
    }
};

class RARCompression : public CompressionStrategy {
    void compress(const std::string& filename) override {
        // RAR压缩实现
        std::cout << "使用RAR算法压缩: " << filename << std::endl;
    }
};
3. 游戏AI系统
class AICharacter {
public:
    void setBehavior(std::unique_ptr<AIBehavior> behavior) {
        behavior_ = std::move(behavior));
    }
    
    void update() {
        behavior_->execute(*this);
    }

private:
    std::unique_ptr<AIBehavior> behavior_;
};

class AggressiveBehavior : public AIBehavior {
    void execute(AICharacter& character) override {
        // 攻击最近的玩家
        auto target = findNearestEnemy();
        character.attack(target);
    }
};

class DefensiveBehavior : public AIBehavior {
    void execute(AICharacter& character) override {
        // 寻找掩体并治疗
        if (character.health < 50) {
            character.findCover();
            character.heal();
        }
    }
};

class PatrolBehavior : public AIBehavior {
    void execute(AICharacter& character) override {
        // 沿预定路径巡逻
        character.followPatrolRoute();
    }
};

策略模式与其他模式的关系

模式关系区别
命令都封装操作命令封装请求,策略封装算法
工厂常结合创建策略对象工厂创建对象,策略管理算法
状态结构相似,意图不同状态管理状态转换,策略管理算法选择
模板方法都涉及算法模板方法固定结构,策略完全替换算法

组合使用示例:

// 策略模式 + 工厂模式
class StrategyFactory {
public:
    std::unique_ptr<SortStrategy> createSortStrategy(SortType type) {
        switch (type) {
            case SortType::QUICK: return std::make_unique<QuickSort>();
            case SortType::MERGE: return std::make_unique<MergeSort>();
            case SortType::HEAP: return std::make_unique<HeapSort>();
            default: throw std::invalid_argument("未知排序类型");
        }
    }
};

// 使用
auto factory = StrategyFactory();
context.setStrategy(factory.createSortStrategy(SortType::MERGE));

策略模式的挑战与解决方案

挑战解决方案
策略类膨胀使用函数对象或lambda表达式
客户端了解策略细节结合工厂模式封装创建逻辑
策略间数据共享通过上下文传递共享数据
动态策略切换开销实现策略对象池

Lambda策略示例

class PaymentContext {
public:
    using Strategy = std::function<bool(double)>;
    
    void setStrategy(Strategy strategy) {
        strategy_ = std::move(strategy));
    }
    
    bool processPayment(double amount) {
        return strategy_(amount);
    }

private:
    Strategy strategy_;
};

// 使用
PaymentContext context;
context.setStrategy([&](double amount) {
    std::cout << "处理现金支付: ¥" << amount << std::endl;
    return true;
});
context.processPayment(100.0);

总结

策略模式是算法管理的终极解决方案,它通过:

  • 算法封装:每个算法独立成类

  • 动态切换:运行时改变算法行为

  • 解耦设计:分离算法与使用上下文

  • 扩展自由:轻松添加新算法

适用场景

  • 需要多种算法变体

  • 算法需要自由切换

  • 需要消除条件语句

  • 算法需要复用和扩展

"策略模式不是简单的算法替换,而是将算法提升为一等公民。它是灵活性的架构基石。" — 设计模式实践者

更多推荐