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

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

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

一、核心思想与角色

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

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

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

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

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

#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; // 微信OpenIDpublic: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);// 支付订单1std::cout << "=== 订单1支付 ===" << std::endl;payment->pay(99.9);// 切换为微信支付,支付订单2std::cout << "\n=== 订单2支付 ===" << std::endl;payment->setStrategy(wechat);payment->pay(199.5);// 切换为银联支付,支付订单3std::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. 避免策略膨胀:当策略过多时,可结合享元模式共享策略对象,或使用组合模式拆分复杂策略。

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

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

相关文章:

  • 接口安全测试实战:从数据库错误泄露看如何构建安全防线
  • h5游戏网站建设做网站被网警找
  • 微美全息(NASDAQ:WIMI)融合区块链+AI+IoT 三大技术,解锁物联网入侵检测新范式
  • Shiro_认证绕过漏洞复现:原理详解+环境搭建+渗透实践(CVE-2020-1957)
  • 三维实时渲染应用开发及场景设计
  • RK3588 + 银河麒麟部署 swarm 集群指南
  • 基于 PyTorch 实现 MNIST 手写数字识别
  • 网站建设找王科杰信誉wordpress企业产品列表
  • 深入 Spring 依赖注入底层原理
  • WebRTC技术如何实现音视频通话
  • 韩国免费行情网站的推荐理由门户网站建设工作会议
  • Python psycopg2 教程
  • 5CEBA2U15I7N 阿尔特拉 Altera Cyclone V FPGA
  • 辉县市工程建设网站建设网站做宣传的免费渠道有那种
  • 2025年10月13日总结
  • perl-Test-Simple-1.302195-5.fc39.noarch.rpm 怎么安装?Fedora 39 安装步骤讲解
  • 图像处理之浓度(AI 调研)
  • 问答网站建设怎么提问郑州网站建设网络推广
  • T:堆的基本介绍
  • Spide - Personal Blog Magazine WordPress Theme Download
  • 使用江科大串口发送函数发送freertos的vTaskList出现跑飞
  • 关于做书的网站中国人做跨电商有什么网站
  • asp网站上传到服务器上之后一打开就是download嘟嘟嘟在线观看播放免费
  • 网站域名审核时间兰州做网站一咨询兰州做网站公司
  • Transformer实战(22)——使用FLAIR进行语义相似性评估
  • Kubernetes:初始化集群(导入Rancher2)
  • 通用:JVM垃圾回收机制
  • Shell脚本技巧:去除文件中字符串两端空白
  • python内置模块-re模块介绍使用
  • JavaWeb后端实战(事务文件上传[本地上传与阿里云OSS上传])