MVC(模型-视图-控制器)图解——输入、更新、渲染
MVC 模式的工作原理,在一张交互式画布上讲清楚:用户输入如何到达控制器、更新模型,模型再通知视图重新渲染。
MVC 用一条规则把应用分成三部分:控制器处理输入,模型拥有状态与规则,视图渲染模型——而视图和控制器都不直接碰状态。
MVC(模型-视图-控制器)图解——输入、更新、渲染
The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.
How to read this visual
- 按箭头画出的顺序走这个循环:用户到控制器,到模型,到视图,再回到用户。
- 三列就是三幕:输入到达,状态更新,输出渲染。
- 泳道就是关注点分离——每条泳道负责一类工作,谁也不干别人的活。
输入
“用户与界面交互”启动这个循环,而“控制器接收输入”是那个指挥交通的角色:它读取动作,判断它意味着什么,再指示模型。控制器上的注释把规则说明白了——它自己不持有任何状态,所以它可以处理大量请求而什么都不用记住。
更新
“控制器更新模型”跨进模型的泳道,而“模型持有状态与业务规则”就是模型的定义:它是数据以及管住这些数据的那些规则的唯一可信来源。“模型把变更通知给观察者”是通知那一半——模型并不告诉视图该画什么,它只宣布有东西变了,任意数量的视图都可以监听。
渲染
“视图根据模型重新渲染”是视图唯一的工作:读模型,把它显示出来。它的注释指出了那条防止 MVC 塌掉的纪律——视图从不改动数据,它只询问和显示。“用户看到更新后的界面”在用户那一行合上了这个圆,而每一次交互也正是从这里开始、在这里结束。
Key relationships and takeaways
- 控制器处理输入;模型拥有状态;视图负责渲染——三种职责,三条泳道。
- 视图和控制器都不写数据;所有变更都流经模型。
- 模型是通知观察者,而不是命令视图,所以一个模型可以驱动多个视图。
- 这种分离让每一部分都能单独测试——这正是这个模式最初带来的回报。
- MVC 是许多现代模式的祖先(MVVM、MVP、Redux 式的状态库),它们保留的都是同一套分离。
When to use this visual
- 在开发者去读某个框架的文档之前,先把这个模式讲给他听——这个三角就是每个框架都在实现的那张地图。
- 解释一个代码库为什么难改:状态被放在视图里处理,这违反 MVC,而且在画布上一眼就能看见。
- 把 MVC 与整洁架构那张图解里的分层架构做对比。
运作方式
把你的框架映射到这个三角上
用你框架里真实的部件重命名这三个方框——路由文件当控制器、ORM 模型当模型、模板当视图——让这个模式变得具体。
加上路由这一步
如果你的框架有路由,就在用户和控制器之间插一个路由步骤,并连到它分发到的那个控制器。
画出多个视图
再加一个视图方框,让两个视图同时监听同一个模型——一个列表视图和一个详情视图——来演示这个模式所依赖的观察者关系。
补上持久化层
在模型后面扩出一个数据库步骤,并注明它归模型所有,控制器和视图从不直接碰它。
常见问题
什么是 MVC?
MVC——模型、视图、控制器——是一种把应用分成三部分的软件模式:控制器处理输入,模型拥有数据和业务规则,视图渲染模型。这种分离的好处是每一部分都可以独立开发和测试,同一个模型也可以被多个视图展示。大多数 Web 框架都建立在这个模式之上。
为什么模型是 MVC 的中心?
因为模型是唯一可信来源。如果控制器和视图都能写数据,它们就会各自漂移、为状态打架。把所有变更都放在模型里,意味着数据规则只存在于一个地方,而视图永远只是一个一致模型的投影。图上把模型的两个方框放进它自己的泳道,正是因为这个原因。
如果我把逻辑写进视图会怎样?
你会得到一种有时被称为“胖视图”的反模式:显示代码和业务规则混在一起,不渲染就没法测试,还会和模型渐行渐远。同样的批评也适用于一个持有业务逻辑、而不是把它委派出去的控制器。MVC 的纪律就是各条泳道各守其位——图上那三行分开的方框,就是这条规则被画了出来。
MVC 和现代框架是什么关系?
大多数现代框架都用新名字保留了这个三角:MVVM 加了一层视图模型,MVP 给视图配了一个展示器,而 Redux 这类状态管理库本质上就是加了更严格通知规则的模型。画布上的核心循环——输入改变状态,状态驱动输出——是它们每一个都保住的不变量。
在 QueryChart(FlowJam)中编辑这张图解
把上面这张 MVC 画布原样打开成你自己的图表,把方框改成你框架里的名字,追一遍你自己的请求路径。