【Architectural Pattern】Model – View – Controller (MVC)

Posted by 西维蜀黍 on 2018-11-11, Last Modified on 2018-11-11

1 背景

MVC (Model - View - Controller)架构是一种当前非常流行的架构模式(Architectural Pattern),被广泛使用于传统的桌面GUI(Graphical user interface)、Web应用和手机移动应用中。

  • 1979年,MVC的概念被 Trygve Reenskaug 在 Smalltalk提出。这种架构模式,极大地降低了GUI应用程序的管理难度,而后被大量用于构建桌面和服务器端应用程序;
  • 从1996年后,MVC逐渐被广泛应用;
  • 2002年,基于Java的Web应用框架Spring引入了MVC的概念;
  • 2005年,基于PythonDjango和基于RubyRails也引入了MVC的概念。

2 原始的MVC

在最初以Smalltalk实现中MVC概念中,MVC是由组合模式(Composite Pattern)、策略模式(Strategy Pattern)和观察者模式(Observer Pattern)三种设计模式组合而成的。

Model-View-Controller (MVC)架构模式中定义一个应用中包括三种角色:模型(Model)、视图(View)和控制器(Controller)

在MVC架构模式中,不仅定义了各个角色的职能,还明确了各个角色之间相互通信的方式。

关于 user action:

  • 在前端框架的 MVC 中,由 View 接收到用户的交互操作,进而View传给Controller。
  • 在后端框架的 MVC 中,由 Controller 直接接收 HTTP request,因此 User action 是给 Controller。
  • d

2.1 设计模式解析

在原始MVC的这个架构模式中,涉及到了三种设计模式:

  • Composite pattern:一个View(对应模式中的Composite)是一系列嵌套的View(对应模式中的Leaf)的组合
  • Strategy pattern:一个Controller实现了一个到多个View(分别对应模式中的ConcreteStragegyA,ConcreteStragegyB)。根据实际情况,确定Controller返回哪一个View给用户
  • Observer pattern: 一个Model对象会维护一系列关注Model状态变化的View。当该Model对象(对应模式中的Subject)状态发生变化时,对应的View(对应模式中的Observer)就会收到通知。

2.2 角色职能

Models

Models 层仅仅包括纯粹的业务逻辑(Bussiness Logic),通常还会将数据持久化(即Models 层包括将数据从数据库中存储和提取的逻辑)

而不关心数据在UI界面中如何展示与呈现。

View

View层关注于数据的呈现,并且提供用户与数据交互(体现为对数据的增删查改)的场所。

View 层通过可视化(visual)的方式(User Interface)将用户感兴趣的数据展示出来,用户可通过与View进行交互实现对数据的增删查改(CURD)或进行相应的业务操作。

Controller

Controller层作为一个位于View层与Model层之间的协调者(intermediary),体现为处理用户交互,即,处理用户的输入和交互,并访问Model层,获取希望得到的数据,最终选择一个View,将数据显示出来。

2.3 通信方式

当用户在 View 层中触发一个行为时(比如点击了一个Button),一个事件就产生了,Controller层会收到这个事件。

此时,Controller可以调用Model层,以触发特定的业务逻辑。或者,Controller也可以直接返回一个View或者在UI界面上作出相应变化。


由于特定View可以注册成为特定Model的观察者(Observer),当特定的Model的状态变化时,特定的View会收到通知,进而更新自己的UI界面(以告知用户特定的事件发生了)。

2.4 分析

在这个最初的MVC模型中,Model层与View层是存在耦合的

我们指定View代表UI界面,仅关注于数据的显示和与用户的交互,而Model代表业务逻辑,仅关注于对业务逻辑的处理。而两者存在耦合,则意味着复用性(Reusability)降低了,同时可维护性(Maintainability)也降低了。

因此,我们渴望存在一种更完美的MVC模式,可以解耦Model层与View层。

3 优化后的MVC

同样地,优化后的Model-View-Controller (MVC)架构模式仍然包括三种角色:模型(Model)、视图(View)和控制器(Controller),且三种角色所负责的职能也并没有改变。

然而,在通信方式上进行了优化,即Controller将完全ViewModel解耦了。

3.1 角色职能

与上面的原始的MVC中的角色职能完全相同。

即:

  • Models 层仅仅包括纯粹的业务逻辑(Bussiness Logic)
  • View 层通过可视化(visual)的方式(User Interface)将用户感兴趣的数据展示出来
  • Controller层作为一个位于View层与Model层之间的协调者(intermediary),以处理用户的输入和交互

3.2 通信方式

当用户在 View 层中触发一个行为(体现为发送一个 RequestController 的形式)时,Controller层会访问Model层(体现为调用Model层中的方法),紧接着在Model层中执行相应的业务逻辑处理,并将结果返回给Controller层。Controller层在收到结果后,将结果发给View(体现为返回一个Response的形式)。注意,这里Controller在收到Model发来的结果后,可能会对这个原始结果进行一定的处理。

View层与Model层没有直接的交互。换句话说,View层只与Controller层交互,Controller层只与Model层交互。

4 MVC在不同框架中的应用

4.1 ASP.NET Web Forms

ASP.NET Web Forms最初的设计思想与Windows Forms类似,即为了简化开发工作,Microsoft为我们提供了很多常用的数据显示与交互控件(比如复选框 CheckList,单选按钮框 RadioButtonList,下拉列表DropDownList等等)。

当我们通过数据绑定(Data Binding)将数据源(比如数据库,XML文件等等)与这些控件绑定后,即可实现无需编写任何代码,就可将数据在Web UI界面中显示出来。

因此,可以看出,View层与Model层是存在耦合的(因为View直接访问了数据持久化层)。


同时,在Controller管理用户的输入和交互逻辑,需要的时候还会访问Model层,最终显示一个新的View或者将处理结果反映在View中。

因此,Controller耦合于Model,也同时耦合于View。所以ASP.NET Web Forms中的MVC对应于最初提到的原始的MVC

4.2 ASP.NET MVC

Overview of ASP.NET Core MVC 中提到,ASP.NET Core MVC 中的 MVC 交互如下所示:

这与ASP.NET Web Forms中的MVC也是完全相同的,即都是原始的MVC


而我认为,在实践使用中的 ASP.NET Core MVC,View往往是不直接访问Model的,而是访问Controller

在此种情况下,ViewModel就不再存在耦合了。这种实践中的MVC与上文描述的优化后的MVC是一致的。

4.3 Cocoa MVC

4.4 Java JSP

在Java JSP中,MVC 是这样体现的:JSP(view) + Servlet(controller) + JavaBean(model)。

  1. 当控制器收到来自用户的请求;
  2. 控制器调用JavaBean完成业务;
  3. 完成业务后通过控制器跳转JSP页面的方式给用户反馈信息(控制器选择一个JSP(View)给用户作为响应)。

4.5 Spring MVC

4.6 Ruby on Rails

待补充…

5 意义

5.1 前后端并行开发

由于MVC解耦了前端(View)与后端(Model),前端和后端开发者可以并行的进行开发而不会发生相互阻塞(Block)对方工作的情况。

具体来说,当前后端协商并确定相互交互的数据协议(或称为数据结构,比如以一个 XMLJSON 的形式),前端开发者可以认为后端开发已经完成,只要根据数据协议传入指定的参数,即可得到希望得到的数据(而无需关注后端的实际开发进度)。相反,后端开发者只要根据数据协议,提供相应的数据(如以 XMLJSON 的形式),而无需关注数据在前端以何种形式呈现出来(从而无需关注前端的实际开发进度)。

5.2 代码复用

对于前端页面(View),前端页面仅仅囊括将数据显示出来的职能(而不包括任何将数据进行提取的职能)。因此,前端页面相对更容易被复用。

类似地,对于后端API,如果希望获得特定的数据,只要请求对应的API即可(即使在不同的前端页面)。同理,复用性同样得到了提升。

6 应用

MVC最初推出被应用于桌面GUIs应用,然而在不久之后也被引入到Web应用(Web Application)中。

在Web应用中,又可以将MVC应用在服务端(Server Side)或客户端(Client Side)中。

6.1 应用于服务端

用户通过浏览器在View中触发一个request请求(比如,以GETPOST的形式)发送到服务端的ControllerController调用Model以完成业务逻辑的处理并得到结果,并将结果返回给客户端的ViewView最终将获得的结果显示出来。

将MVC应用于服务端的框架包括DjangoRailsASP.NET MVC

6.2 应用于客户端

而在 AngularJSEmberJSJavaScriptMVCBackbone等框架中,所有MVC组件的交互过程仅仅只在客户端发生。

Reference