跳转到内容

MVC

本页使用了标题或全文手工转换
维基百科,自由的百科全书

这是本页的一个历史版本,由Misaka0xFFF留言 | 贡献2015年7月21日 (二) 08:46编辑。这可能和当前版本存在着巨大的差异。

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC模式最早由Trygve Reenskaug在1978年提出[1] ,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程式设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:

  • (控制器 Controller)- 负责转发请求,对请求进行处理。
  • (视图 View) - 界面设计人员进行图形界面设计。
  • (模型 Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
MVC模式

组件的互动

MVC组件之间的典型合作

除了将应用程序划分为三种组件,模型 - 视图 - 控制器(MVC)设计定义它们之间的相互作用。[2]

  • 模型(Model) 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“ Model ”有对数据直接访问的权力,例如对数据库的访问。“Model”不依赖“View”和“Controller”,也就是说, Model 不关心它会被如何显示或是如何被操作。但是 Model 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而,View 可以了解在数据 Model 上发生的改变。(比较:观察者模式软件设计模式))
  • 视图(View)能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。
  • 控制器(Controller)起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。

优点

在最初的JSP网页中,像数据库查询语句(SQL query)这样的数据层代码和像HTML这样的表示层代码是混在一起。虽然有着经验比较丰富的开发者会将数据从表示层分离开来,但这样的良好设计通常并不是很容易做到的,实现它需要精心地计划和不断的尝试。MVC可以从根本上强制性地将它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它带给我们的好处是毋庸置疑的。

首先,多个 View 能共享一个 Model 。如今,同一个Web应用程序会提供多种用户界面,例如用户希望既能够通过浏览器来收发电子邮件,还希望通过手机来访问电子邮箱,这就要求Web网站同时能提供Internet界面和WAP界面。在MVC设计模式中, Model 响应用户请求并返回响应数据,View 负责格式化数据并把它们呈现给用户,业务逻辑和表示层分离,同一个 Model 可以被不同的 View 重用,所以大大提高了代码的可重用性。

其次,Controller 是自包含(self-contained)指高獨立內聚的物件,与 Model 和 View 保持相对独立,所以可以方便的改变应用程序的数据层和业务规则。例如,把数据库从MySQL移植到Oracle,或者把RDBMS数据源改变成LDAP数据源,只需改变 Model 即可。一旦正确地实现了控制器,不管数据来自数据库还是LDAP服务器,View 都会正确地显示它们。由于MVC模式的三个模块相互独立,改变其中一个不会影响其他两个,所以依据这种设计思想能构造良好的少互扰性的构件。

此外,Controller 提高了应用程序的灵活性和可配置性。Controller 可以用来连接不同的 Model 和 View 去完成用户的需求,也可以构造应用程序提供强有力的手段。给定一些可重用的 Model 、 View 和Controller 可以根据用户的需求选择适当的 Model 进行处理,然后选择适当的的 View 将处理结果显示给用户。

評價及适用范围

MVC模式的缺点是由于它没有明确的定义,所以完全理解MVC模式并不是很容易。使用MVC模式需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。开发一个MVC模式架构的工程,将不得不花费相当可观的时间去考虑如何将MVC模式运用到应用程序中,同时由于Model和 View 要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。另外由于MVC模式将一个应用程序分成了三个部件,所以这意味着同一个工程将包含比以前更多的文件。

過去MVC模式并不适合小型甚至中等规模的应用程序,这样会带来额外的工作量,增加应用的复杂性。但現在多數軟體設計框架,能直接快速提供MVC骨架,供中小型應用程序開發,此問題不再存在。对于开发存在大量用户界面,并且逻辑复杂的大型应用程序,MVC将会使软件在健壮性、代码重用和结构方面上一个新的台阶。尽管在最初构建MVC模式框架时会花费一定的工作量,但从长远的角度来看,它会大大提高后期软件开发的效率。

实现

微软所推出的MFC Document/View架构是早期对于MVC模式的实现,MFC將程式分成CView以及CDocument兩大類別,其中的Document对应MVC中的 Model ,View 相当于MVC中的 View+Controller,再加上CWinApp類別,合成三大項。但是基本上MFC是一個失敗的MVC模式作品。

由於MFC之下的Document/View 定義過於模糊,未將Controller(MessageMap)部份取出,因此 Controller 可以置入 View 或Document,但不管置入哪一方面,都會與View或Document綁死,沒有彈性。

Java 平台企业版 (J2EE)

和其他的各种框架不一样,J2EE为模型对象(Model Objects)定义了一个规范。

视图(View)
在J2EE应用程序中,视图(View)可能由Java Server Page(JSP)擔任。生成 View 的代码则可能是一个servlet的一部分,特别是在客户端服务端交互的时候。
控制器(Controller)
J2EE应用中,Controller 可能是一个servlet
除了可直接以J2EE來撰寫外,亦可用其他框架來撰寫,常見的有Struts2Spring Framework……等等。
模型(Model)
Model 则是由一个实体Bean来实现。

Java Swing

Swing是一个标准的MVC结构. ComponentUI代表 View, 负责描画组件. 组件尤其 Model 层, 比如JTextField的Document, JTable的TableModel, JTree的TreeModel等等. 而Control可能不是很明显, 我们或许可以简单的将其Event机制看作一个Swing团队开发给开发者的 Controller。

作为Java开发者, 如果想理解MVC的结构, 学习Swing的确是个不错的选择.

Android中界面部分也采用了当前比较流行的MVC框架,在Android中:

视图(View)
一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如果你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为 View 层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。
控制器(Controller)
Android的控制层的重任通常落在了众多的Activity的肩上,这句话也就暗含了不要在Activity中写代码,要通过Activity交割 Model 业务逻辑层处理,这样做的另外一个原因是Android中的Activity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
模型(Model)
对数据库的操作、对网络等的操作都应该在 Model 里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。

ASP.NET

在ASP.NET中,针对视图(View)和控制器(Controller)的模式没有被很好地定义。而模型(Model)则留给开发者去设计。

视图(View)
ASPX和ASCX文件被用来处理 View 的职责。在这个设计中 View 实际上是从 Controller 继承而来。这个和Smalltalk的实施有所不同,在Smalltalk中不同的类都有指针互相指向对方.
控制器(Controllers)
Controller 的职责被分割成两部分。事件(Event)的产生和传输是框架的一部分,更明确的说是Page和Control两个类。而事件的处理则在分离的代码中实现。
模型(Model)
ASP.NET 不严格需要一个 Model。开发者可以自行选择创建一个 Model 类,但是很多人选择放弃这一步,直接把事件处理放在 Controller 里处理任何计算、数据保存等等。但用 Model 来包含商业逻辑和数据存取是可实现的。

ASP.NET MVC

此外,在ASP.NET MVC中,一般情況下Model通常搭配LINQ to SQL類別(使用O/R Designer工具所製作而成的DBML檔)或ADO.NET實體資料模型(Entity Data Model,使用ADO.NET Entity Framework製作出的EDMX檔)來實作。

Windows Forms

在WinForms中,这个针对视图(View)和控制器(Controller)的模式已经很好的定义。而模型(Model)则留给开发者去设计。

视图(View)
由Form或者Control类继承来的一个类处理 View 的职责。在WinForm这个例子中 View 和 Controller 被编译在同一个类中,这个和ASP.NET不同。
控制器(Controller)
Controller 的职责被分割成三部分。事件(Event)的产生和传输是操作系统的一部分。在.Net框架中Form和Control类将不同的事件转发给相应的事件处理器。而事件的处理则在分离的代码中实现。
模型(Model)
就像ASP.NET一样,WinForm不严格需要一个 Model。开发者可以自行选择创建一个 Model 类,但是很多人选择放弃这一步,直接把事件处理放在 Controller 里处理任何计算、数据保存等等。也就是说用Model来包含商业逻辑和数据存取。

Perl

CatalystJifty是透過Perl語言所開發出來的Web Framework,都採用Model-View-Controller 架構。Catalyst 本身只是做了 Controller,View 和 Model 讓開發者自由選用 CPAN 上的模組開發,例如 Template 和 Template Declare 都可用來產生視圖。Jifty 將 MVC 完全實做完成,View 的部份在早期版本使用 Mason 實做,較新版本使用 Template Declare。

Ruby on Rails

Ruby on Rails是透過Ruby語言所開發出來的 Web Framework,也是採用 Model-View-Controller 架構。Model 部份使用 Active Record 概念實做,加上 Migration 機制,使得其 Model 結構非常容易控制。

Python

Python 有許多的 MVC 架構。最常用的有 DjangoTurboGears

JavaScript

ActionScript 3

参考文献

  1. ^ Reenskaug, Trygve. THING-MODEL-VIEW-EDITOR: an Example from a planningsystem (PDF). 
  2. ^ Buschmann, Frank (1996) Pattern-Oriented Software Architecture.
  3. ^ ASP.NET MVC 概觀

外部链接