c++策略模式

场景设定

我们需要设计一个 Hero(英雄)类,他有一个 Attack(攻击)的行为。

英雄可以使用**“剑”攻击,也可以用“火球”攻击,甚至可以“空手”**攻击。

1. 传统的做法(虚函数 + 继承)

在传统 OOP 中,如果不使用策略模式,你可能会觉得:既然攻击方式不同,那就派生出不同的子类吧。

// 基类 class Hero { public: virtual void Attack() { cout << "空手攻击!" << endl; } // 默认虚函数 }; // 派生类:剑士 class Swordsman : public Hero { public: void Attack() override { cout << "挥剑斩击!" << endl; } }; // 派生类:法师 class Mage : public Hero { public: void Attack() override { cout << "发射火球!" << endl; } }; 

这种写法的痛点:

  • 死板:一旦你创建了一个 Swordsman 对象,他就永远只能挥剑。如果他捡到一根魔杖想变成法师怎么办?你没法把一个 Swordsman 对象直接变成 Mage 对象。
  • 类爆炸:如果你有 100 种武器,你难道要写 100 个 Hero 的子类吗?

2. 新写法(std::function + 策略注入)

现在我们用你提到的方法。Hero 不再有子类,它只是一个“容器”,它的 Attack 行为由一个 std::function 变量决定。

我们可以把这个变量理解为英雄装备的**“技能卡槽”**。

A. 定义 Hero 类
#include <iostream> #include <functional> class Hero; // 前置声明 // 定义接口类型:这是一个“函数签名”,它接受一个 Hero 引用,没有返回值 using AttackStrategy = std::function<void(const Hero&)>; // 默认的攻击方式(普通函数) void DefaultPunch(const Hero& h) { std::cout << "英雄使用了:普通拳击 (默认)" << std::endl; } class Hero { public: // 构造函数:默认装备“普通拳击”技能卡 Hero(AttackStrategy strategy = DefaultPunch) : attack_skill(strategy) {} // 公开的非虚函数接口 void DoAttack() { std::cout << "[准备动作] 英雄深吸一口气..." << std::endl; // 核心:调用当前装备的技能卡 attack_skill(*this); std::cout << "[结束动作] 攻击完成。" << std::endl; } // 关键点:我们可以随时更换技能卡! void ChangeWeapon(AttackStrategy new_strategy) { attack_skill = new_strategy; } private: AttackStrategy attack_skill; // 这里保存了具体的“怎么打” }; 
B. 三种不同的实现(举例说明)

现在,可以通过给 attack_skill 赋值不同的内容,让同一个 Hero 对象表现出完全不同的样子。

例子 1:普通函数(最简单的实现)

// 一个普通的全局函数 void UseSword(const Hero& h) { std::cout << ">>> EXCALIBUR! (使用圣剑攻击)" << std::endl; } // 使用: Hero h1(UseSword); h1.DoAttack(); // 输出: // [准备动作] ... // >>> EXCALIBUR! ... 

例子 2:Lambda 表达式(最方便的实现)

有时候我们不想专门写个函数,只想临时定义一个招式,比如“扔石头”。

// 使用 Lambda 直接定义逻辑 Hero h2([](const Hero& h) { std::cout << ">>> 扔出了一块石头!(Lambda实现)" << std::endl; }); h2.DoAttack(); 

例子 3:成员函数 + std::bind(最复杂的实现,也是你困惑的地方)

假设我们有一个复杂的 MagicBook(魔法书)类,里面存了很多法术。这些法术是 MagicBook 的成员函数,而不是全局函数。

class MagicBook { public: void CastFireball(const Hero& h) { std::cout << ">>> 这里的魔法书:发射大火球!" << std::endl; } void CastIceStorm(const Hero& h) { std::cout << ">>> 这里的魔法书:召唤暴风雪!" << std::endl; } }; 

现在问题来了:MagicBook::CastFireball 也是一个函数,但它的参数其实有两个:(MagicBook* this, const Hero& h)。

而我们的 std::function 只接受一个参数 (const Hero& h)。签名不匹配!

这就好比插头(函数)是三孔的,但插座(std::function)是两孔的。

std::bind 就是那个转接头。 它把 MagicBook 的对象实例(this)直接“焊死”在函数上,让它对外看起来只剩下一个参数。

int main() { MagicBook myBook; // 我有一本魔法书对象 // 创建一个英雄 Hero h3; // 1. 英雄想用魔法书里的火球术 // 这里的 bind 意思:把 myBook 绑定到 CastFireball 的第一个参数(this)上 // std::placeholders::_1 表示:Hero 参数留空,等调用的时候再填 h3.ChangeWeapon(std::bind(&MagicBook::CastFireball, &myBook, std::placeholders::_1)); h3.DoAttack(); // 输出:发射大火球! // 2. 英雄想换成冰风暴 h3.ChangeWeapon(std::bind(&MagicBook::CastIceStorm, &myBook, std::placeholders::_1)); h3.DoAttack(); // 输出:召唤暴风雪! return 0; } 

总结对比

特性传统虚函数写法std::function 写法 (策略模式)
实现方式class Swordsman : public Heroh.ChangeWeapon(UseSword)
切换行为不可能 (你是剑士就一辈子是剑士)极易 (运行

Read more

【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈大数据技术原理与应用 ⌋ ⌋ ⌋专栏系统介绍大数据的相关知识,分为大数据基础篇、大数据存储与管理篇、大数据处理与分析篇、大数据应用篇。内容包含大数据概述、大数据处理架构Hadoop、分布式文件系统HDFS、分布式数据库HBase、NoSQL数据库、云数据库、MapReduce、Hadoop再探讨、数据仓库Hive、Spark、流计算、Flink、图计算、数据可视化,以及大数据在互联网领域、生物医学领域的应用和大数据的其他应用。 【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/BigData_principle_application。 文章目录 * 一、读数据的过程 * 二、写数据的过程 * 小结 在介绍 HDFS 的数据读写过程之前,需要简单介绍一下相关的类。FileSystem 是一个通用文件系统的抽象基类,可以被分布式文件系统继承,所有可能使用

By Ne0inhk

python满屏无限弹窗表白代码

开发过程 一、准备工作 首先,确保你的电脑上已经安装了Python环境。我们需要安装Tkinter是Python标准库中的一个GUI(Graphical User Interface,图形用户界 面)工具包,其目的是为Python开发者提供快捷创建GUI应用程序的方式。 二、编写代码 接下来,我们将通过编写一个简单的Python脚本来实现满屏无限弹窗的效果。以下是一个基本的示例代码: import tkinter as tk import random as ra import threading as td import time as ti import sys # 定义爱心文字列表,增加多样性 love_texts = [ '我喜欢你', '❤️', '喜欢你', 'love

By Ne0inhk

最新AI-Python自然科学领域机器学习与深度学习技术

技术点目录 * 一、科研数据类型与预处理 夯实建模起点:理解模型本质,规范预处理流程 * 二、模型评估、验证与不确定性量化 科研可信度的基石:不止于准确率 * 三、高维与复杂结构数据降维 从高维噪声中提取主导模态 * 四、时频分析与谱方法 揭示周期、突变与多变量协同机制 * 五、高级回归建模:超越线性假设 超越线性假设,适配多样响应类型 * 六、机器学习核心算法 高精度预测与非线性预测工具箱 * 七、可解释人工智能(XAI) 让模型“说出理由”:支持科学归因与机制推断 * 八、深度学习:感知与表征 处理图像与光谱 * 九、深度学习进阶:序列、生成与注意力 建模动态演化、生成模拟与长程依赖 * 十、时空数据建模技术 专门应对自然系统的核心挑战:时空依赖与耦合 * 了解更多 ———————————————————————————— 随着观测技术、数值模拟与计算基础设施的迅猛发展,地球系统科学、

By Ne0inhk
【原创实践】Python 将 Markdown 文件转换为 Word(docx)完整实现

【原创实践】Python 将 Markdown 文件转换为 Word(docx)完整实现

Python 将 Markdown 文件转换为 Word(docx)完整实现 在实际开发中,经常会遇到将 Markdown 文档转换为 Word(.docx)的需求,例如: * 技术文档从 Markdown 迁移到 Word * 自动生成可下载的 Word 报告 与 Dify、FastAPI 等系统结合做文档导出 本文基于 python-docx + markdown + BeautifulSoup,实现一个不依赖接口、直接读取 Markdown 文件并生成 Word 文件的完整方案,支持常见 Markdown 语法。 参考链接 https://mp.weixin.qq.com/s/vyz5d9Hya9UEEEvOiro9Vg 一、实现思路说明 整体转换流程如下:

By Ne0inhk