餐厅点餐,教会我MVC, MVP, MVVM

54 阅读6分钟

1.MVC:传统老派餐厅

从餐厅点餐系统看不同模式区别.png

场景:一家传统餐厅,老板亲自管理一切。

  • Model(菜单和订单):
  • View(顾客看到的菜单和订单看板):
    • 纸质菜单
    • 墙上的订单状态看板
  • Controller(老板兼服务员):
    • 接收顾客点餐请求
    • 亲自修改订单Model
    • 亲自通知后厨做菜
    • 亲自更新墙上看板
    • 亲自送菜到桌上

工作流程:

顾客点鱼香肉丝     → 老板听到(Controller接收事件)     → 老板在手写订单上记录(更新Model)     → 老板跑到后厨喊:"做一份鱼香肉丝!"(调用业务逻辑)     → 老板跑回来更新看板"1号桌:制作中"(更新View)     → 老板等菜好了,亲自端给顾客

特点:

  • 老板全能但疲惫:Controller掌握所有细节
  • 紧密耦合:老板知道菜单纸的每个细节、后厨的每个流程
  • 扩展困难:老板生病,餐厅停摆;想加电子菜单要重写整套流程

2. MVP:规范化连锁餐厅

从餐厅点餐系统看不同模式区别 (5).png

场景:标准化管理的连锁餐厅。

  • Model(中央订单系统):
  • View(iPad点餐界面+状态显示屏):
    • 顾客操作的iPad点餐界面
    • 桌边的"订单状态"LED屏
  • Presenter(餐厅经理系统):
    • 验证库存
    • 计算价格
    • 调用中央系统创建订单
    • 通知后厨系统
    • 告诉LED屏显示什么
    • 从中央系统获取状态
    • 格式化后推送给LED屏
  • 关键机制:
    • View变得"愚蠢", 只显示经理告诉它显示的内容, 所有逻辑交给经理
    • Presenter全权负责
      • 更新Model
      • 调用业务
      • 控制View显示

工作流程:

顾客在iPad选"宫保鸡丁"     → iPad说:"经理,顾客选了宫保鸡丁"     → 经理系统:        

  1. 检查库存(业务逻辑)        
  2. 在中央系统创建订单(更新Model)        
  3. 通知后厨制作        
  4. 告诉iPad:"显示'已接受'"        
  5. 告诉LED屏:"显示预计10分钟"    

→ 后厨完成 → 通知经理 → 经理更新所有显示

优点:

  • 职责清晰:经理专注逻辑,界面专注显示
  • 易于测试:可以单独测试经理系统
  • 可替换View:iPad坏了换安卓平板,经理系统不用改

缺点:

  • 经理越来越胖:所有功能都加到Presenter里
  • 手动同步:经理要记住更新每个显示设备

3. MVVM:智能未来餐厅

从餐厅点餐系统看不同模式区别 (4).png

场景:全自动化智能餐厅。

  • Model(云端订单系统):
  • View(智能餐桌+AR菜单):
    • 不是命令式控制
  • ViewModel(餐厅智能大脑)
    • 响应式数据
    • 变化自动传播
    • 命令绑定到界面操作
    • 自动同步到云
    • 当云Model变化时自动触发

工作流程:

  1. 顾客在AR菜单隔空点"水煮鱼"    → 触发ViewModel的selectDish命令    → 自动同步到云Model
  2. 后厨机器人开始制作    → 云Model的progress从0开始增加    → ViewModel的cookingProgress自动同步(因为绑定了)    → 餐桌的进度条自动动画(因为绑定了ViewModel)
  3. 完成时:    云Model.status = "完成"    → ViewModel.currentStatus自动变成"完成"    → 状态显示自动变绿色(computed属性)    → 送餐机器人自动出发(绑定了状态变化事件)

核心优势:

  • 自动同步:无需手动更新UI
  • 声明式编程:说"我要显示进度",而不是"先获取进度值,再设置进度条..."
  • 高度解耦:ViewModel不知道具体是哪个设备在显示

工程化对比分析

数据流对比

从餐厅点餐系统看不同模式区别 (3).png

模式数据流向类比
MVCView → Controller → Model → View顾客喊 → 老板跑 → 记录 → 老板改看板
MVPView → Presenter → Model → Presenter → View按iPad → 经理处理 → 系统记录 → 经理告诉各处更新
MVVMView ↔ ViewModel ↔ Model(自动双向)点菜 → 系统自动流转 → 所有设备自动同步

代码复杂度对比

python

# MVC:老板式代码
def handle_order():
    dish = get_from_view()      # 从界面拿数据
    validate(dish)              # 验证逻辑
    order.add(dish)             # 更新Model
    kitchen.notify(dish)        # 业务调用
    update_display()            # 手动更新UI
    update_printers()           # 手动更新其他设备
    # 每加一个设备都要改这里!

# MVP:经理式代码
class Presenter:
    def on_order(dish):
        # 所有逻辑集中在此
        self.model.add(dish)
        self.view.show_status("处理中")
        self.kitchen.make(dish)
        # View越多,方法越多

# MVVM:智能系统
class ViewModel:
    @observable selectedDish = None
    
    @command
    def select_dish(dish):
        self.selectedDish = dish  # 设置这个,一切自动发生

测试友好度

测试类型MVCMVPMVVM
业务逻辑难测(依赖UI)容易(Presenter可独立测试)很容易(ViewModel纯逻辑)
UI交互需要UI自动化需要模拟View接口可通过绑定测试
集成测试复杂中等简单(关注数据流)

上位机开发的实战选择

适合MVC的场景

  • 小型工控设备,功能简单
  • 快速原型开发
  • 传统WinForms桌面应用

csharp

// 适合:小型温控器界面
buttonStart.Click += (s, e) => {
    var temp = textBoxTemp.Text;  // 直接从View取
    controller.SetTemperature(temp);  // Controller处理
    labelStatus.Text = "运行中";  // 直接更新View
};

适合MVP的场景

  • 复杂工业控制系统
  • 需要严格测试的生产系统
  • 多版本客户端(Web/桌面/移动)

csharp

// 适合:SCADA监控系统
public interface IAlarmView {
    void ShowAlarm(string message);
    void UpdateStatus(DeviceStatus status);
}

public class AlarmPresenter {
    private IAlarmView view;
    private AlarmModel model;
    
    public void OnDeviceAlert(Device device) {
        var alarm = model.CreateAlarm(device);
        view.ShowAlarm(alarm.Message);  // 控制View显示
        // 可测试的业务逻辑
    }
}

适合MVVM的场景

  • 现代WPF上位机软件
  • 数据可视化大屏
  • 需要实时同步的多终端系统

xml

<!-- WPF上位机:PLC数据监控 -->
<Window>
    <Grid>
        <!-- 声明式绑定,自动更新 -->
        <Gauge Value="{Binding Pressure, Mode=TwoWay}" 
               MaxValue="{Binding MaxPressure}" />
        
        <Chart Data="{Binding TemperatureHistory}" 
               Visibility="{Binding IsMonitoring, Converter=...}" />
               
        <Button Command="{Binding StartCommand}" 
                Content="启动" />
    </Grid>
</Window>

架构演进启示

从传统到现代的进化

  1. MVC(手工时代)

    text

    如:每个按钮事件写200行代码
    问题:改个布局要重写逻辑
    
  2. MVP(工业化时代)

    text

    如:Presenter处理所有业务,View变薄
    进步:可测试,但Presenter会膨胀到5000
  3. MVVM(智能化时代)

    text

    如:数据绑定 + 响应式编程
    飞跃:UI与逻辑解耦,开发效率倍增
    

现代上位机开发建议

# 推荐架构:MVVM + 分层
┌─────────────────────────────────┐
│          View (WPF/Qt)          │ ← 纯UI,数据绑定
├─────────────────────────────────┤
│      ViewModel (Reactive)       │ ← 响应式状态管理
├─────────────────────────────────┤
│      Service/Use Case层         │ ← 业务逻辑(可测试)
├─────────────────────────────────┤
│   Repository/Device Access层    │ ← PLC/设备通信
├─────────────────────────────────┤
│       Model/Entity层            │ ← 数据模型
└─────────────────────────────────┘

关键决策点

  1. 选择MVP如果

    • 团队熟悉传统模式
    • 系统复杂度高但UI相对稳定
    • 需要详细的单元测试覆盖
  2. 选择MVVM如果

    • 使用WPF、Qt Quick等现代框架
    • UI交互复杂,需要数据绑定
    • 追求开发效率和可维护性

结论:就像餐厅从老板亲力亲为,到专业分工,再到智能自动化,软件架构也在不断演进。现代上位机开发,MVVM已成为主流选择,它能更好地应对日益复杂的工业4.0需求。