跳转到内容

C++ 策略模式

来自代码酷

C++策略模式[编辑 | 编辑源代码]

策略模式(Strategy Pattern)是一种行为设计模式,它允许在运行时选择算法的行为。这种模式定义了一系列算法,并将每个算法封装起来,使它们可以互相替换,且算法的变化不会影响使用算法的客户端。

介绍[编辑 | 编辑源代码]

策略模式属于对象行为模式,它通过将算法封装在独立的类中,使得它们可以独立于使用它们的客户端而变化。这种模式特别适用于当一个系统需要在多种算法中选择一种时,或者当一个类有多种行为,而这些行为在类的操作中以多个条件语句的形式出现时。

策略模式的主要组成部分包括:

  • Context(上下文):使用策略的类,维护一个对策略对象的引用。
  • Strategy(策略):定义所有支持的算法的公共接口。
  • ConcreteStrategy(具体策略):实现策略接口的具体算法。

代码示例[编辑 | 编辑源代码]

以下是一个简单的C++示例,展示策略模式的实现:

#include <iostream>
#include <memory>

// 策略接口
class Strategy {
public:
    virtual void execute() const = 0;
    virtual ~Strategy() = default;
};

// 具体策略A
class ConcreteStrategyA : public Strategy {
public:
    void execute() const override {
        std::cout << "Executing Strategy A\n";
    }
};

// 具体策略B
class ConcreteStrategyB : public Strategy {
public:
    void execute() const override {
        std::cout << "Executing Strategy B\n";
    }
};

// 上下文类
class Context {
private:
    std::unique_ptr<Strategy> strategy;
public:
    explicit Context(std::unique_ptr<Strategy> strat) : strategy(std::move(strat)) {}
    
    void setStrategy(std::unique_ptr<Strategy> strat) {
        strategy = std::move(strat);
    }
    
    void executeStrategy() const {
        if (strategy) {
            strategy->execute();
        }
    }
};

int main() {
    Context context(std::make_unique<ConcreteStrategyA>());
    context.executeStrategy();  // 输出: Executing Strategy A
    
    context.setStrategy(std::make_unique<ConcreteStrategyB>());
    context.executeStrategy();  // 输出: Executing Strategy B
    
    return 0;
}

输出:

Executing Strategy A
Executing Strategy B

类图[编辑 | 编辑源代码]

以下是策略模式的类图表示:

classDiagram class Strategy { <<interface>> +execute()* } class ConcreteStrategyA { +execute() } class ConcreteStrategyB { +execute() } class Context { -strategy: Strategy +setStrategy(Strategy) +executeStrategy() } Strategy <|-- ConcreteStrategyA Strategy <|-- ConcreteStrategyB Context o-- Strategy

实际应用场景[编辑 | 编辑源代码]

策略模式在以下场景中特别有用:

1. 支付系统:不同的支付方式(信用卡、PayPal、银行转账)可以作为不同的策略实现。 2. 压缩工具:支持多种压缩算法(ZIP、RAR、7z),用户可以动态选择。 3. 导航系统:根据交通状况(最快路线、最短距离、避开收费站)选择不同的路径计算策略。

支付系统示例[编辑 | 编辑源代码]

以下是一个简化的支付系统示例:

#include <iostream>
#include <memory>

// 支付策略接口
class PaymentStrategy {
public:
    virtual void pay(double amount) const = 0;
    virtual ~PaymentStrategy() = default;
};

// 信用卡支付
class CreditCardPayment : public PaymentStrategy {
public:
    void pay(double amount) const override {
        std::cout << "Paying " << amount << " using Credit Card\n";
    }
};

// PayPal支付
class PayPalPayment : public PaymentStrategy {
public:
    void pay(double amount) const override {
        std::cout << "Paying " << amount << " using PayPal\n";
    }
};

// 支付处理器
class PaymentProcessor {
private:
    std::unique_ptr<PaymentStrategy> strategy;
public:
    void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strat) {
        strategy = std::move(strat);
    }
    
    void processPayment(double amount) const {
        if (strategy) {
            strategy->pay(amount);
        }
    }
};

int main() {
    PaymentProcessor processor;
    
    processor.setPaymentStrategy(std::make_unique<CreditCardPayment>());
    processor.processPayment(100.50);  // 输出: Paying 100.5 using Credit Card
    
    processor.setPaymentStrategy(std::make_unique<PayPalPayment>());
    processor.processPayment(75.25);   // 输出: Paying 75.25 using PayPal
    
    return 0;
}

优缺点[编辑 | 编辑源代码]

优点[编辑 | 编辑源代码]

  • 可以在运行时切换算法
  • 将算法的实现与使用算法的代码分离
  • 避免使用多重条件语句
  • 符合开闭原则(对扩展开放,对修改关闭)

缺点[编辑 | 编辑源代码]

  • 客户端必须了解不同的策略
  • 增加了对象的数量
  • 策略间的通信可能需要额外的上下文信息

数学表示[编辑 | 编辑源代码]

策略模式可以形式化表示为: 解析失败 (语法错误): {\displaystyle Context = (S: Strategy) \rightarrow execute() \\ Strategy = \{s_1, s_2, ..., s_n\} \\ \forall s_i \in Strategy, s_i.execute() \text{ 提供特定实现} }

总结[编辑 | 编辑源代码]

策略模式是处理算法变化的强大工具,它通过将算法封装在独立的类中,使得它们可以独立变化。这种模式特别适用于需要动态选择算法或需要避免使用复杂条件语句的场景。通过策略模式,代码变得更加灵活、可维护和可扩展。