第12章 文档与视图
MFC提供了将应用程序的数据与显示分开的文档-视图结构,它为应用程序提供了统一的框架,参见图12-1和图12-2。MFC的文档-视图结构是MVC模式的一种部分实现。
应用程序对象 指向:● 创建 文档模板 指向:● 创建 创建 文档对象 指向:● 框架窗口 指向:● 创建 视图对象 指向:● 图12-1 SDI应用程序中的对象 图12-2 文档-视图结构中各种对象及其创建与关系
12.1 MVC
MVC是一种软件架构模式,通过分解程序的不同功能,达到降低程序设计的复杂度、利于程序员专业分工、简化程序的维护和扩展的目的。MVC是1979年挪威计算机科学家Trygve Reenskaug在Xerox(施乐公司)PARC(Palo Alto Research Center,帕洛阿尔托研究中心)工作时,为(历史上第二个面向对象程序设计语言和第一个真正的集成开发环境)SmallTalk提出的。
12.1.1 概念
MVC(Model-View-Controller,模型—视图—控制器)是一种软件架构模式,它把软件系统分为如下三个基本部分(参见图12-3):
? 模型(Model)—— 数据(库)。 ? 视图(View)—— 图形界面(表示)。
1
? 控制器(Controller)—— 程序功能(算法)。
图12-3 MVC模式的关系图
MVC模式的目的是实现一种动态的程序设计,简化对程序的后续修改和扩展,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。
软件系统通过对自身基本部份分离的同时,也赋予了各个基本部分应有的功能,专业人员可以通过自身的专长进行分组合作:数据库专家利用“模型”进行数据管理和数据库设计、界面设计人员利用“视图”进行图形界面设计、而程序员则利用“控制器”编写程序应有的功能(实现算法等等)。
12.1.2 层次
模型(Model,数据模型)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权利,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。(比较:观察者模式(软件设计模式))
视图(View) 视图层能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。
控制器(Controller) 控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。
2
12.1.3 实现
? SmallTalk
1980年MVC最早被应用于Xerox PARC的面向对象、动态类型、自反射的编程语言SmallTalk-80环境中,运行在首个具有GUI的原型计算机Alto(男高音)上。
? MacApp
1985年Apple将MVC用于其推出的Mac OS系统的面向对象的应用程序框架MacApp中,这是MVC首次在商用产品中的实际应用。
? MFC
1993年2月微软在其随Visual C++ 1.0推出的MFC 2.0中,引入了文档-视图(Document / View)架构,它也是一种对于MVC的早期部分实现。MFC将程序分成视图(View)和文档(Document)两大类,其中的CDocument对应MVC中的数据模型(Model),CView相当于MVC中的视图+控制(View+Controller),再加上应用程序类CWinApp,合成三大项。
但是MFC基本上是一个失败的MVC作品。由于MFC对Document/View的定义过于模糊,未将Controller(消息映射)部份取出,因此Controller既可置入View也可置入Document,但不管置入哪一方面,都会与View或Document绑死而缺乏弹性。
? Java EE——Struts
1999年12月Sun推出的Java EE(Java Enterprise Edition,Java企业版,原来叫J2EE)和其他的各种框架不一样,它为模型对象(Model Objects)定义了一个规范。典型例子是由Craig McClanahan于2000年5月所开发的开源Java EE轻型Web应用框架Apache Struts。
? 视图(View) —— 在JAVA EE应用程序中,视图(View)可能由JSP(Java Server
Page,爪哇服务器网页)承担。生成视图的代码则可能是Servlet的一部分,特别是在客户端服务端交互的时候。
? 控制器(Controller) —— JAVA EE应用中,控制器可能是一个Servlet。 ? 模型(Model) —— 模型则是由一个实体Bean来实现。 ? .NET——Windows Forms
2002年2月微软所推出的.NET框架中还包含有WinForms(视窗窗体),这个针对视图(View)和控制器(Controller)的模式已被很好地定义,而模型(Model)则留给开发者去设计。
? 视图(View)—— 由Form或者Control类继承来的一个类处理视图的职责。
3
在WinForm这个例子中视图和控制器被编译在同一个类中,这个和ASP.NET不同。
? 控制器(Controller)—— 控制器的职责被分割成三部分。事件(Event)的产
生和传输是操作系统的一部分。在.Net框架中Form和Control类将不同的事件转发给相应的事件处理器。而事件的处理则在分离的代码中实现。 ? 模型(Model)—— 就像ASP.NET一样,WinForm不严格需要一个模型。开
发者可以自行选择创建一个模型类,但是很多人选择放弃这一步,直接把事件处理放在控制器里处理任何计算、数据保存等等。也就是说用模型来包含商业逻辑和数据访问。
? .NET——ASP.NET
2002年2月微软随.NET推出了ASP.NET,针对视图(View)和控制器(Controller)的模式并没有被很好地定义,模型(Model)也留给开发者去设计。
? 视图(View)——ASPX和ASCX文件被用来处理视图的职责。在这个设计中
视图实际上是从控制器继承而来。这个和Smalltalk的实施有所不同,在Smalltalk中不同的类都有指针互相指向对方。
? 控制器(Controller)—— 控制器的职责被分割成两部分。事件(Event)的产生
和传输是框架的一部分,更明确的说是Page和Control两个类。而事件的处理则在分离的代码中实现。
? 模型(Model)—— ASP.NET 不严格需要一个模型。开发者可以自行选择创
建一个模型类,但是很多人选择放弃这一步,直接把事件处理放在控制器里处理任何计算、数据保存等等。但用模型来包含商业逻辑和数据访问是可实现的。
2009年4月9日微软推出了ASP.NET MVC 1.0,它在ASP.NET 3.5运行库之上提供了一个新的MVC架构。此架构为Web应用程序文件夹(folder)结构定义了一个特别模式,并提供了一个控制器基类来处理“动作(actions)”请求。ASP.NET MVC 2.0将随.NET框架4.0和Visual Studio 2010一起推出。
12.2 文档-视图体系
文档(document)对应于用户的数据(可以是文本、数值、图像、声音、视频等),它可以从磁盘文件中读入,也可写入磁盘文件,用户还可以创建、修改和管理这些数据。文档
4
对应的MFC类为CDocument。
视图(view)是一种窗口对象,对应于框架窗口的客户区,它负责在屏幕和打印机上显示和输出数据,为用户提供观察、选择、编辑文档数据的交互界面(参见图12-4)。视图对应的MFC类为CView。
文档-视图结构有两种主要的方式:SDI(Single Document Interface,单文档界面)和MDI(Multiple Document Interface,
图12-4 文档与视图
多文档界面)。从MFC 7.0起新增加了一种MTDI(Multiple Top-level Document Interface,多顶级文档界面),参见图11-5。
SDI
传统MDI
选项卡式MDI
MTDI
图11-5 不同的文档界面
SDI应用程序只有一个框架窗口(类)和一个视图窗口(对应于框架窗口的客户区),且只有一个文档类,每次只能打开一个文档。这里的文档和视图一般是一一对应的。例如Windows中的记事本、写字板和画图等软件,是典型的SDI应用程序。
MDI应用程序有一个主框架窗口(类),可有任意多个子框架窗口和对应的视图客户区窗口,也可有多个文档类,可以同时打开多个文档/窗口。这里,每个视图对应于一个文档,而每个文档则可对应于多个视图,参见图12-6。例如Word 2000和IE 8,分别是传统和选卡式MDI应用程序。
MTDI类似于MDI,只是MDI中的每个文档视图窗口都是主框架窗口的子窗口(只能位于主框架窗口的客户区内)。而MTDI的文档视图窗口都是顶层窗口,位于主框架窗口之外。例如新版Word和老版IE,就是典型的MTDI应用程序。
应用程序的文档-视图结构种类,可以在创建MFC应用程序时,在“MFC应用程序向导”对话框的“应用程序类型”页中设置(默认为MDI),在该对话框页中还可以选择是否
5
图12-6 一个文档可对应多个视图