MVC
MVC(Model-View-Controller) 是一种软件设计模式,用于将应用程序分为三个主要组件:模型(Model)、视图(View) 和控制器(Controller)。它通过分离关注点(Separation of Concerns)提高代码的可维护性、可扩展性和可测试性,广泛应用于 Web 应用、桌面应用和移动应用开发。
核心组件
模型(Model)
- 负责管理应用的数据和业务逻辑。
- 直接与数据库、API 等数据源交互。
- 当数据变化时,通知视图更新。
视图(View)
- 负责呈现数据(UI)给用户。
- 监听模型变化并更新界面。
- 不处理业务逻辑,仅展示数据。
控制器(Controller)
- 接收用户输入(如点击、表单提交)。
- 调用模型处理数据。
- 根据模型状态选择合适的视图展示结果。
工作流程
MVC 的数据流通常遵循以下步骤:
- 用户交互:用户通过视图触发操作(如点击按钮)。
- 控制器接收请求:视图将用户输入传递给控制器。
- 控制器处理请求:控制器调用模型的方法处理业务逻辑。
- 模型更新数据:模型执行操作(如查询数据库、计算结果)。
- 模型通知视图:数据变化后,模型通知视图更新。
- 视图刷新界面:视图获取最新数据并重新渲染。
用户 → 视图 → 控制器 → 模型 → 视图(更新)示例:简单的待办事项应用
以下是一个简化的 MVC 实现示例(使用 JavaScript):
1. 模型(Model)
javascript
class TodoModel {
constructor() {
this.todos = [];
this.observers = [];
}
// 添加观察者(视图)
addObserver(observer) {
this.observers.push(observer);
}
// 通知所有观察者数据已更新
notifyObservers() {
this.observers.forEach((observer) => observer.update());
}
// 添加待办事项
addTodo(text) {
this.todos.push({ id: Date.now(), text, completed: false });
this.notifyObservers();
}
// 删除待办事项
removeTodo(id) {
this.todos = this.todos.filter((todo) => todo.id !== id);
this.notifyObservers();
}
// 获取所有待办事项
getAll() {
return this.todos;
}
}2. 视图(View)
javascript
class TodoView {
constructor(controller) {
this.controller = controller;
this.container = document.createElement("div");
this.render();
}
// 渲染视图
render() {
this.container.innerHTML = `
<input type="text" id="todo-input" placeholder="添加待办事项">
<button id="add-button">添加</button>
<ul id="todo-list"></ul>
`;
// 绑定事件到控制器
document.getElementById("add-button").addEventListener("click", () => {
const input = document.getElementById("todo-input");
this.controller.addTodo(input.value);
input.value = "";
});
}
// 更新视图(由模型通知)
update() {
const todoList = document.getElementById("todo-list");
todoList.innerHTML = "";
const todos = this.controller.getTodos();
todos.forEach((todo) => {
const li = document.createElement("li");
li.textContent = todo.text;
li.innerHTML += ` <button data-id="${todo.id}">删除</button>`;
li.querySelector("button").addEventListener("click", () => {
this.controller.removeTodo(todo.id);
});
todoList.appendChild(li);
});
}
}3. 控制器(Controller)
javascript
class TodoController {
constructor(model) {
this.model = model;
}
// 添加待办事项
addTodo(text) {
if (text.trim()) {
this.model.addTodo(text);
}
}
// 删除待办事项
removeTodo(id) {
this.model.removeTodo(id);
}
// 获取所有待办事项
getTodos() {
return this.model.getAll();
}
}4. 初始化应用
javascript
// 创建 MVC 实例并关联
const model = new TodoModel();
const controller = new TodoController(model);
const view = new TodoView(controller);
// 将视图添加到 DOM
document.body.appendChild(view.container);
// 注册视图为模型的观察者
model.addObserver(view);MVC 的变体
MVVM(Model-View-ViewModel)
- 使用 ViewModel 替代 Controller,通过数据绑定自动同步视图和模型。
- 典型框架:Vue.js、Angular。
MVP(Model-View-Presenter)
- Presenter 与 View 强耦合,负责处理视图逻辑。
- 常用于测试驱动开发(TDD)。
Flux/Redux
- 单向数据流架构,更适合复杂应用状态管理。
优缺点
| 优点 | 缺点 |
|---|---|
| 分离关注点,提高代码可维护性 | 架构复杂度较高,小型应用可能冗余 |
| 支持并行开发(视图和逻辑分离) | 控制器可能变得庞大(Massive Controller) |
| 便于单元测试(模型和控制器可独立测试) | 视图与模型的双向依赖可能导致紧耦合 |
适用场景
- 中大型应用,尤其是需要多人协作开发的项目。
- 需要频繁修改视图或业务逻辑的场景。
- 需要支持多种视图展示同一数据的应用(如 Web 端和移动端)。
总结
MVC 是一种经典的软件架构模式,通过分离数据、视图和控制逻辑,使代码更易于维护和扩展。虽然现代前端框架(如 React、Vue)可能采用不同的架构模式(如单向数据流),但 MVC 的核心思想(关注点分离)仍然是软件设计的重要原则。