MVC分层架构模式深入剖析
🔄 MVC 交互流程
💡 核心原则:View 的“被动性”
-
View 只做两件事:
- 展示 UI 元素(按钮、文本框等)
- 将用户事件转交给 Controller(自身不处理业务逻辑)
-
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
会导致:
- 紧耦合:更换 Model 需修改 View 代码
- 无法复用:该 View 只能搭配特定 Model
- 测试困难:需启动完整 UI 才能测试逻辑
✅ MVC 的正确分工总结
组件 | 职责 |
---|---|
View | 1. 渲染界面 2. 转发用户事件 → Controller |
Controller | 1. 接收 View 事件 2. 调用 Model 修改数据 3. 协调更新流程 |
Model | 1. 存储数据/逻辑 2. 数据变更后通知 View(观察者模式) |
简单记忆:View 是秘书(只传递文件),Controller 是经理(做决策),Model 是仓库(保管数据)。