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

命令模式,餐厅订单管理系统C++

一、为什么用命令模式

    在软件设计中,命令模式(Command Pattern)提供了一种将请求封装为对象的方式,从而使请求的发送者和执行者解耦。这在以下场景非常有用:当操作需要支持撤销、排队、延迟执行或日志记录时,命令模式能将逻辑统一管理。

    餐厅点餐系统是典型场景:服务员记录顾客订单,厨师按顺序制作,每道菜可独立撤销或取消,但正在制作的菜不能撤销。直接在服务员或厨师中处理复杂逻辑,会导致代码耦合,难以扩展。使用命令模式,将“下单”“做菜”“撤销”操作封装成独立命令对象,既清晰又易维护。

二、场景说明

    在这个场景中,餐厅的服务员负责接收顾客点餐。每道菜都是一个独立的命令对象,例如“红烧鱼”和“家乡煎豆腐”。顾客下单后,服务员将订单加入队列,但厨师是按顺序做菜的,当前只做一道菜,做完后才开始下一道。

    系统支持顾客在下单后撤销某些菜,但有严格限制:正在烹饪的菜不可撤销,只允许撤销尚未开始的菜。服务员可以继续接收新订单,撤销旧订单,厨师按照队列顺序烹饪所有菜品。这样既满足实际业务需求,也充分体现了命令模式的灵活性和可扩展性。

三、类图

四、C++代码实现

#include <iostream>
#include <memory>
#include <map>
#include <deque>
#include <algorithm>enum class OrderStatus { Pending, Cooking, Done };// 命令接口
class Command {
public:virtual ~Command() = default;virtual void execute() = 0;  virtual void undo() = 0;     
};// 厨师
class Chef {
public:void cookFish() { std::cout << "厨师:开始做红烧鱼!\n"; }void cancelFish() { std::cout << "厨师:取消红烧鱼。\n"; }void cookTofu() { std::cout << "厨师:开始做家乡煎豆腐!\n"; }void cancelTofu() { std::cout << "厨师:取消家乡煎豆腐。\n"; }
};// 具体命令
class FishCommand : public Command {
public:FishCommand(Chef* chef) : chef_(chef) {}void execute() override { chef_->cookFish(); }void undo() override { chef_->cancelFish(); }
private:Chef* chef_;
};class TofuCommand : public Command {
public:TofuCommand(Chef* chef) : chef_(chef) {}void execute() override { chef_->cookTofu(); }void undo() override { chef_->cancelTofu(); }
private:Chef* chef_;
};// 服务员
class Waiter {
public:int takeOrder(std::unique_ptr<Command> cmd) {int id = nextId_++;orders_[id] = { std::move(cmd), OrderStatus::Pending };orderQueue_.push_back(id);std::cout << "服务员:记录订单编号 " << id << "\n";cookNextIfIdle();return id;}void cancelOrder(int id) {auto it = orders_.find(id);if (it != orders_.end()) {if (it->second.status == OrderStatus::Pending) {it->second.command->undo();orderQueue_.erase(std::remove(orderQueue_.begin(), orderQueue_.end(), id),orderQueue_.end());orders_.erase(it);} else {std::cout << "订单 " << id << " 正在做或已完成,无法撤销。\n";}} else {std::cout << "没有找到编号为 " << id << " 的订单。\n";}}private:struct OrderItem {std::unique_ptr<Command> command;OrderStatus status;};void cookNextIfIdle() {if (isCooking_ || orderQueue_.empty()) return;isCooking_ = true;while (!orderQueue_.empty()) {int id = orderQueue_.front();orderQueue_.pop_front();auto it = orders_.find(id);if (it != orders_.end()) {it->second.status = OrderStatus::Cooking;it->second.command->execute();it->second.status = OrderStatus::Done;orders_.erase(it); }}isCooking_ = false;std::cout << "厨师:所有订单已完成。\n";}int nextId_ = 1;bool isCooking_ = false;std::map<int, OrderItem> orders_;std::deque<int> orderQueue_;
};// 测试
int main() {Chef chef;Waiter waiter;int o1 = waiter.takeOrder(std::make_unique<FishCommand>(&chef));int o2 = waiter.takeOrder(std::make_unique<TofuCommand>(&chef));int o3 = waiter.takeOrder(std::make_unique<FishCommand>(&chef));waiter.cancelOrder(o2); // 可以取消豆腐,只要它还没开始做int o4 = waiter.takeOrder(std::make_unique<TofuCommand>(&chef)); // 新下单豆腐return 0;
}

五、总结

    通过这个餐厅点餐示例,我们可以看到命令模式在实际开发中的几个优势:

  1. 解耦请求和执行:服务员只负责接单和管理订单,厨师专注于烹饪逻辑,二者职责清晰分明。

  2. 支持撤销与延迟操作:每道菜都是独立的命令对象,未开始的菜可以随时取消,而正在烹饪的菜则安全执行。

  3. 扩展性强:增加新菜品只需创建新的命令类,无需修改服务员或厨师核心逻辑,符合开闭原则。

  4. 维护方便:通过订单状态管理和队列处理,烹饪顺序和撤销逻辑清晰可控。

这个示例不仅清楚地展示了命令模式的用法,也贴合实际餐厅点餐流程,对于想在 C++ 项目中灵活运用设计模式的开发者,很有参考意义。


文章转载自:

http://o2a1DH2t.jLnLr.cn
http://wgnotovB.jLnLr.cn
http://e71KnVOv.jLnLr.cn
http://h9LEX9P9.jLnLr.cn
http://93f6rXub.jLnLr.cn
http://nnxojVqe.jLnLr.cn
http://aqEXCnWK.jLnLr.cn
http://o2MutaXo.jLnLr.cn
http://eJwUnWqA.jLnLr.cn
http://2pj2MmuA.jLnLr.cn
http://C4AMPovR.jLnLr.cn
http://2j7n6yp2.jLnLr.cn
http://wqxnJ5ZN.jLnLr.cn
http://SGIyjNwN.jLnLr.cn
http://ktTUud37.jLnLr.cn
http://wR4GhxKj.jLnLr.cn
http://MKaZUo9z.jLnLr.cn
http://ZBrVn88w.jLnLr.cn
http://IYb7PTaH.jLnLr.cn
http://dzlHNPsO.jLnLr.cn
http://WZqEpITG.jLnLr.cn
http://norQQqA3.jLnLr.cn
http://Vh9uoCGV.jLnLr.cn
http://9n8iFdFp.jLnLr.cn
http://piLjm3jk.jLnLr.cn
http://FLmy1VZ1.jLnLr.cn
http://1w9n9i6G.jLnLr.cn
http://F3VLFz3T.jLnLr.cn
http://X72WXDfg.jLnLr.cn
http://xUvuSxsC.jLnLr.cn
http://www.dtcms.com/a/379402.html

相关文章:

  • Android EDLA测试命令总结
  • opencv基础实践;银行卡号识别
  • 【录屏软件】 实用工具推荐——电脑录屏软件班迪(Bandicam)录屏图文安装指南
  • 微服务事务管理实践与 Seata 框架解析
  • 今日行情明日机会——20250911
  • P4105 [HEOI2014] 南园满地堆轻絮
  • Docker 命令核心语法、常用命令
  • Windows安装Chroma DB
  • 60_基于深度学习的羊群计数统计系统(yolo11、yolov8、yolov5+UI界面+Python项目源码+模型+标注好的数据集)
  • Linux 命令 top、vmstat、iostat、free、iftop 正常用法和退出.
  • 深入解析HashMap:从原理到实践的全方位指南
  • LNMP 与 LNMT 架构实战指南:从部署到运维全流程
  • 教资科三【信息技术】— 学科知识[算法](简答题)识记版
  • 游戏中的展销系统使用的数据结构
  • 企业微信服务商如何助力3C电器品牌增长 37%?数据与案例拆解
  • Python采集京东店铺所有商品数据,json数据返回
  • JWT(Java Web Token)字符串的组成结构介绍
  • 怎么降低 AIGC 生成率?
  • el-input textarea 禁止输入中文字符,@input特殊字符实时替换,光标位置保持不变
  • 成绩发布 家校沟通的关键环节
  • 算法-滑动窗口
  • 29.线程的互斥与同步(三)
  • 第3节-使用表格数据-DEFAULT约束
  • linux系统安装wps
  • 26. AI-Agent-LangChain
  • 基于51单片机温度控制系统报警器恒温箱蓝牙app控制设计
  • 2025 年 GPU 显卡维修市场:高性能计算时代的刚需支撑
  • 融智学新范式(1992-2000)被认为是先于谷歌同类探索的更全面更深刻的理论研究和实践应用
  • 领码方案|Windows 下 PLT → PDF 转换服务超级完整版:异步、权限、进度
  • IvorySQL 适配 LoongArch® 龙架构