C++设计模式之行为型模式:策略模式(Strategy)

策略模式(Strategy)是行为型设计模式的一种,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户端,从而实现算法的灵活切换。

一、核心思想与角色

策略模式的核心是"算法封装与动态切换",通过将不同算法分离为独立的策略类,使客户端可以根据需求选择或切换算法。其核心角色如下:

角色名称 核心职责
抽象策略(Strategy) 定义所有支持的算法的公共接口,声明算法的执行方法。
具体策略(ConcreteStrategy) 实现抽象策略接口,包含具体的算法逻辑。
环境类(Context) 持有一个策略对象的引用,提供设置策略的接口,在需要时调用策略的执行方法。

核心思想:将算法的定义与使用分离,客户端通过环境类间接使用策略,可在运行时动态更换策略,而无需修改使用算法的代码。

二、实现示例(支付方式选择)

假设我们需要设计一个电商支付系统,支持多种支付方式(如支付宝、微信支付、银联支付),用户可根据需求选择不同支付方式。使用策略模式可将每种支付方式封装为独立策略,实现灵活切换:

cpp 复制代码
#include <iostream>
#include <string>

// 1. 抽象策略:支付方式
class PaymentStrategy {
public:
    // 纯虚方法:执行支付
    virtual void pay(double amount) = 0;
    virtual ~PaymentStrategy() = default;
};

// 2. 具体策略1:支付宝支付
class AlipayStrategy : public PaymentStrategy {
private:
    std::string account; // 支付宝账号

public:
    AlipayStrategy(const std::string& acc) : account(acc) {}

    void pay(double amount) override {
        std::cout << "使用支付宝账号[" << account << "]支付了 " << amount << " 元" << std::endl;
        // 实际支付逻辑:调用支付宝API...
    }
};

// 2. 具体策略2:微信支付
class WechatPayStrategy : public PaymentStrategy {
private:
    std::string openId; // 微信OpenID

public:
    WechatPayStrategy(const std::string& id) : openId(id) {}

    void pay(double amount) override {
        std::cout << "使用微信OpenID[" << openId << "]支付了 " << amount << " 元" << std::endl;
        // 实际支付逻辑:调用微信支付API...
    }
};

// 2. 具体策略3:银联支付
class UnionPayStrategy : public PaymentStrategy {
private:
    std::string cardNumber; // 银行卡号

public:
    UnionPayStrategy(const std::string& card) : cardNumber(card) {}

    void pay(double amount) override {
        std::cout << "使用银联卡[" << cardNumber << "]支付了 " << amount << " 元" << std::endl;
        // 实际支付逻辑:调用银联API...
    }
};

// 3. 环境类:订单支付上下文
class PaymentContext {
private:
    PaymentStrategy* strategy; // 当前支付策略

public:
    // 构造时指定初始策略
    PaymentContext(PaymentStrategy* strat) : strategy(strat) {}

    // 动态更换支付策略
    void setStrategy(PaymentStrategy* newStrat) {
        strategy = newStrat;
    }

    // 执行支付(委托给当前策略)
    void pay(double amount) {
        if (strategy) {
            strategy->pay(amount);
        } else {
            std::cout << "未设置支付方式,支付失败" << std::endl;
        }
    }
};

// 客户端代码:使用支付系统
int main() {
    // 创建具体支付策略
    PaymentStrategy* alipay = new AlipayStrategy("user123@alipay.com");
    PaymentStrategy* wechat = new WechatPayStrategy("o6_bmjrPTlm6_2sgVt7hMZOPfL2M");
    PaymentStrategy* unionpay = new UnionPayStrategy("6222 **** **** 1234");

    // 创建支付上下文(环境类),初始使用支付宝
    PaymentContext* payment = new PaymentContext(alipay);

    // 支付订单1
    std::cout << "=== 订单1支付 ===" << std::endl;
    payment->pay(99.9);

    // 切换为微信支付,支付订单2
    std::cout << "\n=== 订单2支付 ===" << std::endl;
    payment->setStrategy(wechat);
    payment->pay(199.5);

    // 切换为银联支付,支付订单3
    std::cout << "\n=== 订单3支付 ===" << std::endl;
    payment->setStrategy(unionpay);
    payment->pay(599.0);

    // 释放资源
    delete unionpay;
    delete wechat;
    delete alipay;
    delete payment;

    return 0;
}

三、代码解析

  1. 抽象策略(PaymentStrategy)

    定义了pay()纯虚方法,声明所有支付方式必须实现的支付接口,参数为支付金额。

  2. 具体策略

    每种支付方式对应一个具体策略类,实现pay()方法封装各自的支付逻辑:

    • AlipayStrategy:支付宝支付,需要支付宝账号。
    • WechatPayStrategy:微信支付,需要微信OpenID。
    • UnionPayStrategy:银联支付,需要银行卡号。
      每个策略类专注于自身的支付实现,与其他策略相互独立。
  3. 环境类(PaymentContext)

    • 持有当前支付策略的引用(strategy),通过setStrategy()方法支持动态切换策略。
    • 提供pay()方法,将支付操作委托给当前策略的pay()方法,客户端无需直接调用策略。
  4. 客户端使用

    客户端创建具体策略和环境类,通过环境类执行支付;需要更换支付方式时,调用setStrategy()切换策略,无需修改支付逻辑代码。

四、核心优势与适用场景

优势
  1. 算法解耦:将算法与使用算法的客户端分离,算法的修改或新增不影响客户端。
  2. 动态切换:支持在运行时动态更换算法(如示例中切换支付方式),灵活性高。
  3. 代码复用:不同环境可共享同一策略对象,避免代码重复。
  4. 符合开闭原则:新增算法只需添加新的策略类,无需修改现有代码。
  5. 替代条件判断 :用策略选择替代if-elseswitch-case,使代码更清晰。
适用场景
  1. 多种算法可选:如排序算法(快速排序、冒泡排序)、支付方式、折扣计算方式。
  2. 算法需要动态切换:如根据用户设置切换压缩算法、根据网络状况切换传输协议。
  3. 避免算法与客户端耦合:如框架设计中允许用户自定义插件(策略)。
  4. 算法逻辑复杂:当算法包含多个步骤或变体时,封装为策略可提高可读性。

五、与其他模式的区别

模式 核心差异点
策略模式 封装可互换的算法,客户端可动态选择,强调"算法替换"。
状态模式 封装对象的状态,状态决定行为且可自动转换,强调"状态驱动行为"。
模板方法 定义算法骨架,子类实现具体步骤,强调"固定流程+可变步骤"。
工厂模式 用于创建对象,可与策略模式结合(工厂创建策略对象),但不涉及算法执行。

六、实践建议

  1. 策略工厂结合 :使用工厂模式创建策略对象,减少客户端对具体策略的依赖(如PaymentStrategyFactory根据类型创建支付策略)。
  2. 策略缓存复用:对于无状态的策略(如无成员变量的算法),可缓存策略对象避免重复创建(类似单例)。
  3. 策略参数化 :通过构造函数或setter方法为策略传递参数(如示例中的账号信息),提高灵活性。
  4. 避免策略膨胀:当策略过多时,可结合享元模式共享策略对象,或使用组合模式拆分复杂策略。

策略模式的核心价值在于"算法的模块化与动态化",它通过将算法封装为独立策略,使系统能灵活适应算法的变化,同时保持客户端代码的稳定。在需要提供多种可选方案或算法可能频繁变更的场景中,策略模式是实现代码灵活性和可维护性的理想选择。

相关推荐
脏脏a2 分钟前
【C++ 入门】:引用、内联函数与 C++11 新特性(auto、范围 for、nullptr)全解析
开发语言·c++
AA陈超7 分钟前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-28 构建属性菜单小部件控制器
c++·游戏·ue5·游戏引擎·虚幻
恒者走天下9 分钟前
cpp / c++零基础就业学习一站式学习平台
开发语言·c++·学习
qq_4335545417 分钟前
C++ 单调栈
数据结构·c++·算法
fpcc29 分钟前
计算机原理—缓存
c++·缓存
利刃大大1 小时前
【高并发服务器】十二、LoopThreadPool线程池管理模块
服务器·c++·项目
Summer_Uncle1 小时前
【C++学习】对象特性--继承
开发语言·c++·学习
岁忧2 小时前
Go channel 的核心概念、操作语义、设计模式和实践要点
网络·设计模式·golang
艾莉丝努力练剑2 小时前
【Git:基本操作】深度解析Git:从初始Git到熟悉基本操作
大数据·linux·c++·人工智能·git·gitee·指令
CN-Dust3 小时前
【C++】2025CSP-J第二轮真题及解析
开发语言·c++·算法