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

设计模式 Day 8:策略模式(Strategy Pattern)完整讲解与实战应用


🔄 前情回顾:Day 7 重点回顾

在 Day 7 中,我们彻底讲透了观察者模式:

它是典型的行为型模式,核心理念是“一变多知”,当一个对象状态变化时,自动通知所有订阅者。

我们通过 RxCpp 实现了工业级的事件广播系统,实现了多个模块订阅同一个数据源。

实战中,如协议解包系统、GUI 事件响应、股票系统等,都广泛采用观察者机制。

🔁 观察者模式强调“自动推送消息”,而今天我们进入策略模式,它更强调“主动选择行为”!



在这里插入图片描述

策略模式(Strategy Pattern)是行为型设计模式中最具“切换能力”的一个,它的设计哲学非常明确:

将算法(行为)抽象为可替换的策略,使得行为的改变不依赖于使用它的对象本身。

策略模式特别适合处理:

  • 多种业务逻辑切换(如支付方式)
  • 动态选择不同算法(如压缩、路径规划)
  • 可扩展、可配置的“策略中心”

本篇 Day 8,将从“动机、结构、语法、实战场景、项目代码、面试回答”六大维度,构建你对策略模式的完整掌握。


一、设计动机:为什么要用策略模式?

✅ 需求背景举例:

  • 一个支付接口,支持支付宝、微信、银行卡……你会怎么设计?
  • 一个路径规划功能,支持最短路、最便宜路径、最快路径……如何实现动态切换?

如果使用 if-else 分支写法:

if (type == "alipay") {
    ...
} else if (type == "wechat") {
    ...
}

✅ 缺点:

  • 不符合开闭原则
  • 不方便扩展新策略
  • 无法复用策略逻辑

这时就需要策略模式!


二、结构定义与核心要点

✅ UML 类图结构

+------------------+
|   Strategy       |<------------------------------+
+------------------+                               |
| + execute()      |                               |
+------------------+                               |
        /\                                          |
        ||                                          |
+-------------------+     +-----------------------+ |
| AlipayStrategy     |     | WeChatStrategy        | |
+-------------------+     +-----------------------+ |
| + execute()        |     | + execute()           | |
+-------------------+     +-----------------------+ |
                                                   |
              +------------------------------+     |
              |     PaymentContext           |-----+
              +------------------------------+
              | - strategy: Strategy*        |
              | + setStrategy(Strategy*)     |
              | + pay()                      |
              +------------------------------+

✅ 角色说明

角色职责
Strategy策略接口,声明统一算法方法
ConcreteStrategy具体策略类,封装各自逻辑
Context上下文,持有当前策略对象

三、完整 C++ 实现

✅ 抽象策略接口

class PaymentStrategy {
public:
    virtual void pay(int amount) = 0;
    virtual ~PaymentStrategy() = default;
};

✅ 具体策略类

class AlipayStrategy : public PaymentStrategy {
public:
    void pay(int amount) override {
        std::cout << "使用支付宝支付: " << amount << " 元" << std::endl;
    }
};

class WeChatStrategy : public PaymentStrategy {
public:
    void pay(int amount) override {
        std::cout << "使用微信支付: " << amount << " 元" << std::endl;
    }
};

class CreditCardStrategy : public PaymentStrategy {
public:
    void pay(int amount) override {
        std::cout << "使用信用卡支付: " << amount << " 元" << std::endl;
    }
};

✅ 上下文类

class PaymentContext {
private:
    std::unique_ptr<PaymentStrategy> strategy_;

public:
    void setStrategy(std::unique_ptr<PaymentStrategy> strategy) {
        strategy_ = std::move(strategy);
    }

    void pay(int amount) {
        if (strategy_)
            strategy_->pay(amount);
        else
            std::cout << "未设置支付方式!" << std::endl;
    }
};

✅ 使用示例

int main() {
    PaymentContext context;

    context.setStrategy(std::make_unique<AlipayStrategy>());
    context.pay(100);

    context.setStrategy(std::make_unique<WeChatStrategy>());
    context.pay(200);

    context.setStrategy(std::make_unique<CreditCardStrategy>());
    context.pay(300);
    return 0;
}

四、真实项目中策略模式的应用场景

应用领域策略角色示例
支付系统支付方式切换:微信、支付宝、银行卡
压缩服务gzip、zip、lz4 等算法策略
游戏角色AI攻击策略、防御策略、逃跑策略
电商促销系统折扣策略、满减策略、积分兑换策略
导航/路径规划最快路线、最短路线、避开拥堵路线
编解码框架JSON、XML、YAML 策略
图像处理多种滤镜、降噪算法策略

五、与状态模式、策略模式、工厂模式的对比

对比项策略模式状态模式工厂模式
意图封装行为算法,动态切换封装对象状态与行为封装创建过程,替代 new
变化点行为逻辑状态 + 行为对象类型
是否持有引用Context 中持有策略对象状态机中持有当前状态对象工厂方法中返回具体对象

六、面试表达模板 + 问答技巧

❓面试官:你用过策略模式吗?什么场景?

✅ 回答示例:

“在我们支付平台中使用了策略模式来解耦支付方式。我们定义了 PaymentStrategy 接口,具体实现了 AlipayStrategyWeChatStrategy 等类,业务调用通过 PaymentContext 设置策略并执行。策略模式让新增支付方式变得非常方便,无需改动旧逻辑,只需新增类即可。”

✅ 加分点:

  • 强调“符合开闭原则”
  • 使用 std::unique_ptr 管理生命周期
  • 提出策略配置可从配置文件加载(JSON -> 类)

七、总结回顾 + 记忆口诀

✅ 策略模式关键词:

  • 行为可切换
  • 算法封装
  • 运行时替换
  • 开闭原则
  • 模块解耦

📌 记忆口诀:

“行为封装进策略,替换逻辑不靠 if,扩展功能加新类,变化收敛更灵活。”


八、明日预告:Day 9

命令模式(Command Pattern)实战详解:解耦请求者与执行者,构建可撤销、可重做、可排队的操作系统。

相关文章:

  • Bartender 5 for Mac 多功能菜单栏管理
  • CSS >子元素选择器和空格
  • 2025年第十六届蓝桥杯省赛C++ A组真题
  • nvm list available 无法查看解决办法
  • GEO优化实战指南:构建生成式AI时代的品牌内容霸权
  • 汇舟问卷:国外问卷调查技巧有哪些,具体该怎么操作
  • Linux-内核驱动-makemenu,make modules,make uImage,杂项
  • AI编程案例拆解|基于机器学习XX评分系统-前端篇
  • DAPP实战篇:使用ethersjs连接智能合约并输入地址查询该地址余额
  • 【愚公系列】《Python网络爬虫从入门到精通》048-验证码识别(滑动拼图验证码)
  • Dify智能体平台源码二次开发笔记(3) - 智能体API的三方验证集成
  • 国网B接口云镜控制接口流程详解以及检索失败原因(电网B接口)
  • leetcode 204. Count Primes
  • 《深入理解生命周期与作用域:以C语言为例》
  • 概念辨析:Redis 多路 I/O 复用和多线程
  • MSCKF及可观性总结
  • Elasticsearch:使用稀疏向量提升相关性
  • 修复 WPS 编译错误:缺少:Sub或Function 且出现两个MathType加载项
  • 生物化学笔记:医学免疫学原理15 超敏反应过敏反应(I型[蚊虫叮咬]+II型[新生儿溶血症、突眼型甲亢]+III型+IV型)
  • Ollama调用多GPU实现负载均衡
  • 中国铁建统一企业门户/seo黑帽培训
  • 重庆官网seo分析/西安做推广优化的公司
  • 科技数码app排名/济南seo网站关键词排名
  • 微网站建设应该怎么开发票/乐事薯片软文推广
  • 唐山建设厅官方网站/app拉新推广平台
  • 阿里云服务器 多个网站/网站建设加推广优化