提到MVC,你会想到什么?三层架构?设计模式?JSP?老掉牙?面相对象制造器?
先来听个故事吧。
引子
《我是歌手》后,实力唱将林志炫算是迎来了事业第二春。小N这天想去网上买一张林志炫的正版CD收藏下,和网店小二聊了下。
店小二:不好意思,暂时卖完了,您要是想要的话,可以帮您订一张。
小N想了下,和店小二谈好价格,决定订一张,双方谈妥。
店小二给老板打电话:有个顾客想买林志炫的《One Take》专辑,咱们店里没现货了,您给台湾那边的厂家打电话,让他们发一张过来吧。
老板说:Ok,没问题。
老板于是给台湾唱片行打电话:某某经理你好,麻烦你明天给我寄一张林志炫《One Take》过来吧。
经理说:好的,明天早上就发货。
第二天晚上就到货了,于是店小二马上发货给小N。又过了1天,小N收到CD了,开心的不得了。
我们来分析一下。
这个例子中,涉及到四个人物,小N、店小二、老板、台湾某经理。关系如下图所示:
其实这就是一个简单的MVC流程。
- 服务员对应View,是与用户直接交流,响应用户的交互操作。
- 老板对应Controller,负责接收View传过来的请求以及相应数据,并将加工的请求通知给唱片行经理。
- 台湾唱片行经理对应Model。因为唱片行相对独立,它不依赖于某个实体店而存在,就像Model不依赖于如何被显示或者如何被操作一样。
缘起
MVC模式最早由Trygve Reenskaug大师在1974年参加Xerox论坛时提出,在论文《A note on DynaBook requirements》中,大师说,MVC最初是为了在人类世界模型和电脑数据模型中建立一种桥梁而产生的架构,旨在用同一份模型来满足不同应用场景需求。
MVC模式,最初名称为 Thing-Model-View-Editor模式,在7个月之后,模式更名为Model-View-Control。其中,原Things模块关心user如何触发交互问题,之后被弱化(即之后的Event机制);原Editor模块只负责提供一个用户与一个或多个View模块进行交互的公共接口,此交互过程不经过Model模块。之后Editor模块被强化为Controller,全面负责用户与View、Model的交互。
在Thing-Model-View-Editor 模型演化之后,MVC各模块的原始定义为:
- Model模型层:负责“知识”的供给。Model可以为一个对象,或者包含一组对象的结构体。为了能准确的定位问题,Model应当提供一个能唯一识别问题的部分,这样才真正能够实现Model的复用。
- View视图层:View是它所属Model的展示部分。它的作用是可以最原始的展示所属Model的几个特定属性,并隐藏掉其它属性。因此View扮演的角色类似于一个与展示相关的“过滤器”。
- Controller控制层:controller层是用户与系统联系的纽带。它提供给用户一组可供用户输入的视图集,并且能够保证每一个视图都显示在恰当的位置上。之后,Controller接收到用户在视图层的输入后,将他们转化为特定的消息,并且分发这些消息给相关的Views。
MVC模式出道至今已近40年,但仍威风不减。虽然现今流行的MVC框架大都是经过了优化,各个模块的含义和作用均得到了增强,但是,万变不离其宗,MVC模式的“宗”始终没变,这也是为什么MVC模式能够屹立至今的原因。那到底MVC的“宗”是什么?
不变
世界,每一刻都是崭新的。苏子说“自其变者而观之,则天地曾不能以一瞬。”可是,苏子又说过:“自其不变者而观之,则物与我皆无尽也”。也就是说,变化是绝对的,不变是相对的。从另一个角度来说,变中蕴含着不变。一旦从变中抽象出不变之后,就要解决两个问题:其一,何时变;其二,如何变。其实,这种从变中抽象出不变的过程,正对应了从无框架代码过渡到MVC框架代码的过程。
不变,对应Model层。上文有述,这是MVC诞生的根本。一个好的系统,一定有一个相对稳定的Model层,不然它可以被断定是存在设计缺陷的,不论是从产品层面还是从设计层面。何时变,对应了View层。View层负责接收用户直接的交互,并将交互抽象为事件通知Controller,这解决了何时变要解决的问题。如何变,对应了Controller层,它在可以变的时机,进行了变的行为,并且通知了不变,这也正是“怎么变”的职责所在。
以上,为一次用“不变”来描述“变”的过程。
猛回头
在向身边的人推荐MVC时,我耳边经常飘着这样的话:“MVC,都20多年了,不是早就过时了吗?”
我认为,MVC是否过时可以从两方面进行判断:
- MVC是否还在被使用
- MVC的思想是否已经消亡
对于第一点,我举两个例子:呼风唤雨的Apple公司的开发框架Cocoa至今还在使用MVC模式;GoogleMap的JS API中的对象基类,名字就叫MVC Object。
对于第二点,我觉得这是一个由分母变化而引起的错觉。因为在MVC提出之初,正是计算机软件架构贫瘠的时候,MVC横空出世占领半壁江山,顺水推舟。但是这么多年过去了,各种框架早已“百家争鸣、百花齐放”,MVC不可能不被进一步优化,这些被优化、改进过的框架虽然有可能不再以MVC冠名,但这不代表MVC在它们身上的影响力已经不在。毕竟从抽象层次上,由“变”到“不变”的变化,是只可能被演化,但不可能再被抽象了的变化。
面向对象 VS 面向原型 VS ?
MVC往往和面向对象联系在一起。至少,以传统MVC模式实现的代码带有很强的面向对象的风格。面向对象的编程风格,在一些情况下会把简单的问题变得异常复杂,因此有人说,MVC会把代码小题大做。我觉得,用面向对象的思想来对世界进行建模,难免会有这种情况,因为世界并不是面向对象的。那,世界又如JavaScript支持者那样,是面向原型的吗?
如果,世界既不是面向对象的,又不是面向原型的,那,世界又是什么?