MVC 的定义
MVC 是 Model-View-Controller 的缩写。Model(模型) - View(视图) - Controller(控制器)是一个用于实现图形用户界面(GUI)程序的软件架构模式。
MVC 用于 GUI 开发
MVC 是一种模式
当我们讨论软件开发时,模式指常规角色的组合。在一种模式中,每个角色都有自己的职责并与其他角色进行交互。
软件旨在处理数据。通过长时间的观察,人们发现 GUI 程序的数据处理周期分以下三个步骤:
程序通过用户界面向用户显示数据
用户通过操作用户界面来更改数据并表达意图
程序(通过逻辑)处理数据并响应用户
上面的流程涉及到了几个角色?
答案是三个,数据、用户界面和逻辑。
注:因为用户不属于程序的一部分,所以设计程序时不将它作为角色。
角色 | 职责 |
---|---|
Data | 携带显示给用户的信息或从用户收集的信息 |
User Interface | 显式数据,收集数据,将操作传递给逻辑 |
Logic | 处理数据,响应用户操作,选择适当的用户界面来显示数据 |
随着演进,这三个角色都有了更恰当的名称,Model、View 和 Controller。
下面列出 MVC 各角色间如何交互和各自的一些规则,在你编写自己的 MVC 程序时尽量不要打破这些规则。如果你无意间打破这些规则,你的 MVC 很可能就转变成了 MVC 的某种变体,这将在下面讨论。
Controller:
响应用户命令
操作 Model
为 Model 选择适当的 View,或是为 View 选择合适的 Model
请求 View 去渲染显式 Model
View:
将用户的命令或操作传递给 Controller
View 不一定知道它的 Model 类型
在 Controller 分配具体实例前,View 不知道它的 Model 类的实例(实际的视图模型)
View 知道如何在 Controller 请求时渲染 Model
View 不会直接操作 Model,只有 Controller 可以操作 Model
Model:
Model 可以包含业务逻辑,例如数据存储到数据库
Model 由 Controller 进行控制,由 View 进行渲染
Model 不会主动与 Controller 进行交互,即 Model 无法操作 Controller
Model 不会主动与 View 进行交互,即 Model 无法操作 View
MVC 模式包括多种变体
只要稍加更改限制再合理的重新分配职责,我们就可以得到一些 MVC 模式的变体。
例如,Mode-View-Presenter(MVP) 模式和 Model-View-ViewModel (MVVM) 模式。
由于 MVVM 也是一种流行的模式,所以我们展开讲一讲。
MVVM 模式的核心概念简单来说就是打破 View 和 Model 间的隔阂:
View 知道其 Model 并可以直接操作 Model
ViewModel 直接响应用户操作
ViewModel 可以主动通知 View 如何渲染它(Model)
Controller 的职责被重新分配给了 ViewModel
使用 MVC 模式的优势
要说清楚 MVC 的优势,就要先讲传统的 GUI 程序开发模式 —— RAD(Rapid Application Development 快速应用开发) 。
GUI 程序是事件驱动的。只要是 GUI 程序,无论 Web、移动应用还是桌面程序,理论上我们都可以将所有逻辑写在事件处理程序中。
例如,我们可以在一个按钮事件处理程序中,验证文本框文本,获取下拉列表选项值,检查是否选中了复选框,然后与本地文件系统,数据库或 Web 服务进行通信存储数据。
我们将这种方式称为快速应用开发(RAD)。
RAD 仅适用于小型程序,当程序越来越大时,UI 实例之间的关系开始变得混乱。特别是当多个开发人员正在为同一组 UI 编写代码时,越来越难理解来自其他开发人员的逻辑。维护代码,解决代码冲突和修复错误的成本都会上升。
为了避免这些问题,我们可以做两件事:
将数据和逻辑从事件处理程序分离出来,并将它们集中在某处,以便代码重用
对于集中式数据和逻辑,将它们分成不同的角色和职责
经过数十年的实验和发展,软件行业发现 MVC(及其变体)一直是一个良好且稳定的解决方案。它可以有效地消除 RAD 在大规模开发中引起的问题。
在大型 GUI 项目中应用 MVC 模式的好处包括:
健壮:开发人员只能在正确的位置编写代码。他们可以轻松地理解和重用他人的代码
可测试:UI 很难测试,但与 UI 分离的模型和控制器很容易通过单元测试进行测试。这大大提高了软件质量和开发性能
可扩展:对于 RAD 开发,添加的 UI 元素越多,UI 形成的网络就越复杂。但 MVC 将应用程序的功能划分为小的垂直支柱。每个支柱由一组控制器,视图和模型组成。扩展程序功能时,我们只需不断添加小支柱并按单元测试用例覆盖代码即可
如何实现 MVC 模式
有三种使用 MVC 及其变体的方法:
RAD + MVC 模式:例如 WinForm 是用于 Windows 开发的 RAD 框架,在编写 WinForm 程序时,你可以手动创建 Model、View 和 Controller,而不是将所有代码都放在事件处理程序中,享受 MVC 模式带来的好处
RAD + MVC 框架:为避免重复造轮子,开发人员为那些单纯的 RAD 框架创建了许多可重用的 MVC 框架。
例如 WPF 是用于 Windows 开发的 RAD 框架,PRISM 是一个包含基类并实现了 MVVM 模式的基础结构的框架。使用 PRISM 框架时,你可以通过派生基类轻松创建 View、Model 和 ViewModel,而无需从头构建它们
另一个例子是 Angular 框架。 HTML + JavaScript 是传统的 Web 开发 RAD 框架,但要使用纯 HTML + JavaScript 创建企业级 Web 程序很困难。Angular 是用于 HTML Web 客户端开发的 MVC 框架。一旦你将 HTML 和 Angular 框架结合使用,你的 Web 程序就变成了 MVC 程序
MVC 程序框架:有许多现成的 MVC 程序框架,例如 ASP.NET MVC,ASP.NET Core 和 Spring MVC。使用 MVC 程序框架和使用 RAD + MVC 框架的区别在于:一旦在 MVC 程序框架上构建程序,程序就会被自然地限制为 MVC 程序,你也再无法将其转换为非 MVC 程序。
例如,当你使用 ASP.NET MVC,ASP.NET Core 或 Spring MVC 创建 Web 程序时,项目构建器会自动应用并搭建 MVC 架构, 你的工作就是不断添加模型,视图和控制器以实现客户的需求