🔄 MVC 交互流程
💡 核心原则:View 的“被动性”
View 只做两件事:
- 展示 UI 元素(按钮、文本框等)
- 将用户事件转交给 Controller(自身不处理业务逻辑)
Controller 是真正的决策者:
- 决定如何响应事件
- 操作 Model 修改数据
- 触发 View 更新(或由 Model 自动触发)
🧩 代码示例:PyQt 中的 MVC 实现
# Model(数据层)
class CounterModel:
def __init__(self):
self.value = 0
self.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 = controller
self.label = QLabel("0")
button = QPushButton("点击+1")
# 关键点:View 捕获点击事件,但立刻转交给 Controller
button.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 是仓库(保管数据)。