到目前为止,我们所考察的一些小模式在特定编码任务中是很有用的。还有一些用来组织整个应用的模式,有时候也称作架构模式(architectural pattern)。在本节中,我们将要考察一个能在很多方面帮助我们组织Ajax项目的架构模式,它可以使得代码更容易编写,也更容易维护。
模型—视图—控制器(MVC)描述的是将程序与用户交互的部分和完成其他繁重工作、科学计算或业务逻辑等等的部分很好分离的一种方式。
MVC通常用于大规模的应用,覆盖应用的所有层次或者跨越多个层次。在本章中,我们引入了这个模式,并且展示如何在Web服务器上应用这一模式为Ajax应用提供数据。在第4章中,我们会更侧重于在客户端的JavaScript中应用这一模式。
MVC模式识别出了系统中一个组件所实现的三种角色。模型表示应用的问题域,也就是要解决的问题。一个文字处理应用需要为文档建模;一个地图应用需要为点、栅格、等高线等建模。
视图是程序展现给用户的东西,例如输入表单、图片、文本或者UI组件。视图不一定是图形形式的。例如,在一个声音驱动的程序中,语音提示也是视图。
MVC的黄金定律是视图和模型不应该相互通信。表面上看,这个要求似乎会导致程序的功能不全,但是这正是控制器的作用之所在。当用户按下一个按钮或者填写一个表单时,视图会通知控制器。控制器操作模型并且决定模型上的变化是否需要变化视图。如果需要,它就通知视图更新它自己(见图3-5)。
图3-5 模型—视图—控制器模式的主要组成部分。视图和模型不直接交互,始终通过控制器来进行。控制器可以看作是一个薄的边界层,允许模型和视图通过它来通信,它使得在代码库中实现清晰的职责分离,提高了代码的灵活性和可维护性
这样做的好处就在于,模型和视图可以保持松散耦合,也就是说,它们都不需要深入了解对方的内部实现。很显然,它们还是需要知道足够的事情才能完成工作,但是视图只需要对模型有一些大体上的了解就足够了。

我们来考虑一个库存管理的程序。控制器可以给视图提供一个函数,这个函数根据给定的类别ID返回该类别所有产品的列表,但是视图并不知道这个列表是从哪里来的。在这个程序的第1版中,用来生成列表数组的数据可能是保存在内存中或者保存在纯文本文件中。而在这个程序的第2版中,由于需要处理数量大得多的数据,在架构中加入了一台关系数据库服务器。模型上的这种变化意义重大,需要重写大量的代码。但是,只要控制器仍然能够提供与某个类别匹配的产品列表,对于视图的代码就不会造成任何影响。
类似地,开发视图代码的工程师也可以自由地修改代码,改善应用的可用性。只要遵循控制器所提供的接口上的基本约定,就无需担心会破坏模型中的隐含假设。通过将系统划分为子系统,MVC提供了一种可靠的策略,使得小的代码变更[7]所引起的波动不至于扩散到整个代码库,并且使得负责每个子系统的团队可以在不影响其他团队的情况下,对需求变化做出迅速地响应。
MVC模式通常以一种特殊的方式应用在传统的Web应用开发框架上[8],用来提供组成用户界面的一系列连续的静态页面。当运行Ajax应用时,它需要从服务器获取数据,服务器端提供数据的机制与传统Web应用中相应的机制是类似的。Web服务器风格的MVC对于Ajax而言仍是有益的。鉴于它得到了广泛的理解,我们就从这里开始,然后再去考察更加特定于Ajax的MVC使用方式。
如果你是一个Web开发框架的新手,下面一节可以为你提供必需的信息,以便理解它们如何使Ajax应用更具扩缩性或者更加健壮。另一方面,如果你对于Web层的工具[例如模板引擎、对象关系映射(ORM)工具]或者开发框架(例如Struts、Spring或Tapestry)已经非常熟悉,那么这里讨论的大部分内容对你已经不陌生了,可以跳过本节,直接阅读第4章,在那里我们会讨论一种非常不同的MVC使用方式。







