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

MVC分层架构模式深入剖析

在这里插入图片描述

🔄 MVC 交互流程

User View Controller Model 点击按钮 调用Controller方法(如onButtonClick()) 修改数据(如model.setData()) 自动通知更新(通过观察者模式) 刷新UI User View Controller Model

💡 核心原则:View 的“被动性”

  1. View 只做两件事

    • 展示 UI 元素(按钮、文本框等)
    • 将用户事件转交给 Controller(自身不处理业务逻辑)
  2. Controller 是真正的决策者

    • 决定如何响应事件
    • 操作 Model 修改数据
    • 触发 View 更新(或由 Model 自动触发)

🧩 代码示例:PyQt 中的 MVC 实现

# Model(数据层)
class CounterModel:def __init__(self):self.value = 0self.observers = []  # 观察者列表(View)def add_observer(self, observer):self.observers.append(observer)def increment(self):self.value += 1# 数据变更后通知所有观察者(View)for observer in self.observers:observer.update(self.value)# View(界面层)
class CounterView(QWidget):def __init__(self, controller):super().__init__()self.controller = controllerself.label = QLabel("0")button = QPushButton("点击+1")# 关键点:View 捕获点击事件,但立刻转交给 Controllerbutton.clicked.connect(self.controller.handle_button_click)  layout = QVBoxLayout()layout.addWidget(self.label)layout.addWidget(button)self.setLayout(layout)def update(self, value):  # 被Model调用self.label.setText(str(value))# Controller(逻辑层)
class CounterController:def __init__(self):self.model = CounterModel()self.view = CounterView(self)self.model.add_observer(self.view)  # 注册View为观察者def handle_button_click(self):# View 点击事件最终由 Controller 处理self.model.increment()  # 修改Model# 主程序
app = QApplication([])
controller = CounterController()
controller.view.show()
app.exec_()

❓ 为什么不是 View 直接调用 Model?

若允许 View 直接操作 Model:

# 错误示例(违反 MVC)
class BadView(QWidget):def __init__(self, model):...button.clicked.connect(model.increment)  # View 直接调用 Model

会导致:

  1. 紧耦合:更换 Model 需修改 View 代码
  2. 无法复用:该 View 只能搭配特定 Model
  3. 测试困难:需启动完整 UI 才能测试逻辑

✅ MVC 的正确分工总结

组件职责
View1. 渲染界面
2. 转发用户事件 → Controller
Controller1. 接收 View 事件
2. 调用 Model 修改数据
3. 协调更新流程
Model1. 存储数据/逻辑
2. 数据变更后通知 View(观察者模式)

简单记忆:View 是秘书(只传递文件),Controller 是经理(做决策),Model 是仓库(保管数据)

http://www.lqws.cn/news/199045.html

相关文章:

  • AI驱动的B端页面革命:智能布局、数据洞察的底层技术解析
  • JAVA国际版二手交易系统手机回收好物回收发布闲置商品系统源码支持APP+H5
  • C++--list的使用及其模拟实现
  • [C++] list双向链表使用方法
  • 嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析
  • wpf的converter
  • 【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析
  • Puppeteer API
  • 每日Prompt:治愈动漫插画
  • ubuntu20使用自主探索算法explore_lite实现机器人自主探索导航建图
  • Keil开发STM32生成hex文件/bin文件
  • 数据结构之栈
  • 《绩效管理》要点总结与分享
  • 大数据(2) 大数据处理架构Hadoop
  • Linux(13)——Ext系列文件系统
  • jenkins gerrit-trigger插件配置
  • Python Copilot【代码辅助工具】 简介
  • 数据库系统概论(十七)超详细讲解数据库规范化与五大范式(从函数依赖到多值依赖,再到五大范式,附带例题,表格,知识图谱对比带你一步步掌握)
  • Docker容器部署elasticsearch8.*与Kibana8.*版本使用filebeat采集日志
  • SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
  • 阿里云MaxCompute入门
  • Fetch与Axios:区别、联系、优缺点及使用差异
  • 使用Python和Scikit-Learn实现机器学习模型调优
  • LinkedList、Vector、Set
  • ⚡️ Linux Docker 基本命令参数详解
  • 开源之夏·西安电子科技大学站精彩回顾:OpenTiny开源技术下沉校园,点燃高校开发者技术热情
  • C++2025.6.7 C++五级考题
  • 在Ubuntu上使用 dd 工具制作U盘启动盘
  • 【hadoop】相关集群开启命令
  • STM32的系统滴答定时器简述