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

C++ 设计模式《外卖菜单展示》

👨‍🎓 模式名称:迭代器模式(Iterator)

👦 故事背景:

随着“小明万能校园平台”大获成功,美食外卖成为热门功能之一。每天成百上千的订单进出,小明打算给每个商家都做一个“外卖菜单展示”模块,供 App 客户端遍历显示菜单上的菜品。

但问题出现了……

🌀 没有使用迭代器模式的困扰

各个商家有自己“奇葩”的菜单数据结构:

  • 🧋 奶茶店:菜单是一个 std::vector

  • 🍱 便当店:菜单是一个 std::map<int, MealItem>

  • 🍢 烧烤摊:菜单是一个 std::list

小明展示菜单时,不得不硬写很多重复代码:

void printMilkTeaMenu(std::vector<DrinkItem>& drinks) {for (auto& d : drinks) {std::cout << d.name << " - " << d.price << "\n";}
}void printMealMenu(std::map<int, MealItem>& meals) {for (auto& [id, m] : meals) {std::cout << m.name << " - " << m.price << "\n";}
}void printBBQMenu(std::list<BBQItem>& bbqs) {for (auto& b : bbqs) {std::cout << b.name << " - " << b.price << "\n";}
}

使用迭代器模式:为所有菜单提供统一遍历方式

🧠 关键目标:隐藏底层数据结构,实现统一遍历接口

🎯 抽象定义

🍔 抽象菜单项类(或接口)
class MenuItem {
public:std::string name;double price;MenuItem(std::string n, double p) : name(n), price(p) {}virtual ~MenuItem() = default;
};
🧾 抽象迭代器接口
class Iterator {
public:virtual bool hasNext() = 0;virtual MenuItem* next() = 0;virtual ~Iterator() = default;
};
🧾 抽象菜单接口
class Menu {
public:virtual Iterator* createIterator() = 0;virtual ~Menu() = default;
};

🍱 示例:不同商家实现

奶茶菜单(用 vector 存)
class MilkTeaMenu : public Menu {
private:std::vector<MenuItem> items;
public:Iterator* createIterator() override;MilkTeaMenu() {items.emplace_back("珍珠奶茶", 10);items.emplace_back("波霸奶绿", 12);}void addItem(const MenuItem& item) {items.push_back(item);}const std::vector<MenuItem>& getItems() const {return items;}};class MilkTeaIterator : public Iterator {
private:MilkTeaMenu& milkTeaMenu;int currentIndex;
public:MilkTeaIterator(MilkTeaMenu& coll) : milkTeaMenu(coll), currentIndex(0) {}MenuItem getNext() override {if (hasMore()) {return milkTeaMenu.getItems()[currentIndex++]; }return MenuItem("",0);}bool hasMore() override {return currentIndex < milkTeaMenu.getItems().size(); }
};
烧烤菜单(用 list 存)
class BBQMenu : public Menu {
private:std::list<MenuItem> items;
public:BBQMenu() {items.emplace_back("羊肉串", 20);items.emplace_back("鸡翅", 40);}Iterator* createIterator() override;void addItem(const MenuItem& item) {items.push_back(item);}const std::list<MenuItem>& getItems() const {return items;}};
class BBQIterator : public Iterator {
private:BBQMenu& bbqMenu;std::list<MenuItem>::const_iterator currentIt;
public:BBQIterator(BBQMenu& coll) : bbqMenu(coll) {currentIt = bbqMenu.getItems().cbegin();}MenuItem getNext() override {if (hasMore()) {// Implementation to get the next element from the collectionreturn *currentIt++; // Placeholder}return MenuItem("", 0);}bool hasMore() override {// Implementation to check if more elements are availablereturn currentIt != bbqMenu.getItems().cend(); // Placeholder}
};

✅ 客户端统一遍历:

void printMenu(Menu* menu) {Iterator* it = menu->createIterator();while (it->hasMore()) {std::string element = it->getNext().name;// Process the elementstd::cout << "element= " << element << std::endl;}delete it;
}

🧪 使用:

Iterator* MilkTeaMenu::createIterator() {return new MilkTeaIterator(*this);
}Iterator* BBQMenu::createIterator() {return new BBQIterator(*this);
}int main() {MilkTeaMenu milkTeaMenu;printMenu(&milkTeaMenu);BBQMenu bbqMenu;printMenu(&bbqMenu);return 0;
}

🎯 适用场景总结

适用场景描述
不同集合类型统一遍历vector、list、map 等不同结构
隐藏内部结构客户端不关心菜单内部
支持并发、懒加载遍历支持自定义迭代顺序和惰性加载等

文章转载自:

http://LOpzglPc.kshzr.cn
http://u1SMBvtZ.kshzr.cn
http://agSF8aK8.kshzr.cn
http://6uBZ5qyZ.kshzr.cn
http://Vyxd7LfU.kshzr.cn
http://BK44TYku.kshzr.cn
http://6Tcce1au.kshzr.cn
http://IuI2d4W7.kshzr.cn
http://ZjUccqYK.kshzr.cn
http://OAjB1CnC.kshzr.cn
http://JBMZNLHc.kshzr.cn
http://SmzkPgyW.kshzr.cn
http://9PcnwW6C.kshzr.cn
http://N7IdgjLn.kshzr.cn
http://2uT9Rnc6.kshzr.cn
http://dTueym1a.kshzr.cn
http://GPBJAy4j.kshzr.cn
http://W0cWZflQ.kshzr.cn
http://a7Bm3Tmp.kshzr.cn
http://EIlDiATl.kshzr.cn
http://JIT5AIYC.kshzr.cn
http://V3YD49GZ.kshzr.cn
http://x9cqylA5.kshzr.cn
http://Tev9DSFK.kshzr.cn
http://A9cghu6t.kshzr.cn
http://VTyjuw4e.kshzr.cn
http://kGvEmjHj.kshzr.cn
http://hsP1cY8N.kshzr.cn
http://r1uDjR7v.kshzr.cn
http://R9XlK3AL.kshzr.cn
http://www.dtcms.com/a/373477.html

相关文章:

  • sv语言中压缩数组和非压缩数组
  • C++----验证派生类虚函数表的组成
  • moxa uport1150串口驱动ubantu20.04 5.15内核安装
  • 中州养老项目:登录功能项目鉴权
  • 2025年渗透测试面试题总结-58(题目+回答)
  • [Dify实战]插件编写- 如何让插件直接输出文件对象(支持 TXT、Excel 等)
  • StringBuilder类的数据结构和扩容方式解读
  • SQL 层面行转列
  • XR数字融合工作站赋能新能源汽车专业建设的创新路径
  • 大模型(LLM)安全保障机制(技术、标准、管理)
  • 【LeetCode】String相关算法练习
  • Redis基本数据类型
  • 深度学习(三):监督学习与无监督学习
  • crew AI笔记[5] - knowledge和memory特性详解
  • MyBatis多数据库支持:独立 XML 方案与单文件兼容方案的优劣势分析及选型建议
  • 安卓玩机工具----安卓“搞机工具箱”最新版 控制手机的玩机工具
  • 100、23种设计模式之适配器模式(9/23)
  • Docker网络模式解析
  • ARM处理器基础
  • TDengine 选择函数 First 用户手册
  • 9.8网编基础知识day1
  • 卷积神经网络(CNN):从图像识别原理到实战应用的深度解析
  • 【LeetCode - 每日1题】将整数转换为两个无零整数的和
  • 【超详细图文教程】2025年最新 Jmeter 详细安装教程及接口测试示例
  • MongoDB 常见错误解决方案:从连接失败到主从同步问题
  • Guava中常用的工具类
  • Entity Digital Sports 降低成本并快速扩展
  • 计算机毕业设计选题:基于Spark+Hadoop的健康饮食营养数据分析系统【源码+文档+调试】
  • Rust异步运行时最小实现 - extreme 分享
  • 内网穿透的应用-Navidrome与cpolar本地搭建跨网络访问的云音乐服务器