实现
术语阐述
及
最佳实践
用 PureMVC 创建健壮、易扩展、易维护的客户端程序
附 ActionScript 3 及 MXML 实例
作者
翻译: 张泽远 <51ajax.net@gmail.com>
Tamt
最后更新: 5/19/2008
: Cliff Hall
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、
培训
焊锡培训资料ppt免费下载焊接培训教程 ppt 下载特设培训下载班长管理培训下载培训时间表下载
资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 2 of 44 5/20/2008 11:17 PM
PureMVC 结构 4
• Model 与 Proxy 4
• View 与 Mediator 4
• Controller 与 Command 4
• Façade 与 Core 5
• Observer 与 Notification 5
• Notification可以被用来触发Command的执行 5
• Mediator发送、声明、接收Notification 6
• Proxy发送,但不接收Notification 6
Façade 7
• 具体Façade是什么样子的? 7
• 为程序创建Façade 7
• 初始化Façade 10
Notification 12
• Event与Notification 12
• 定义Notification和Event常量 13
Command 14
• SimpleCommand和MacroCommand的使用 15
• 降低Command与Mediator, Proxy的耦合度 15
• 复杂的操作与业务逻辑 16
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 3 of 44 5/20/2008 11:17 PM
Mediator 21
• Mediator的职责 21
• 转化View Component类型 22
• 监听并响应View Component 23
• 在Mediator里处理Notification 25
• Mediator和Proxy之间、Mediator和其他Mediator之间的耦合 27
• 用户与View Component和Mediator的交互 28
Proxy 33
• Proxy的职责 34
• 转换数据对象 34
• 避免对Mediator的依赖 36
• 封装域逻辑 37
• 与Remote Proxy通信 38
启示
PureMVC 是一个定位于
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
高性能 RIA 客户端的基于模式
的框架。现在它已经被移植到其他的平台上,包括服务器
端环境。本篇文档论述针对于客户端。
PureMVC 在不同平台语言下的阐述、实现,PureMVC 所
使用的模式在“四人帮”的《设计模式:可复用面向对象
软件的基础》一书中有很好的论述。
强烈推荐。
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 4 of 44 5/20/2008 11:17 PM
PureMVC 结构
PureMVC框架的目标很明确,即把程序分为低耦合的三层:Model、View和
Controller。
降低模块间的耦合性,各模块如何结合在一起工作对于创建易扩展,易维护的应用
程序是非常重要的。
在PureMVC实现的经典MVC元设计模式中,这三部分由三个单例模式类管理,分
别是Model、View和Controller。三者合称为核心层或核心角色。
PureMVC中还有另外一个单例模式类——Façade,Façade提供了与核心层通信
的唯一接口,以简化开发复杂度。
Model 与 Proxy
Model 保存对 Proxy 对象的引用,Proxy 负责操作数据模型,与远程服务通
信存取数据。
这样保证了 Model 层的可移植性。
View 与 Mediator
View 保存对 Mediator 对象的引用 。由 Mediator 对象来操作具体的视图组
件(View Component,例如 Flex 的 DataGrid 组件),包括:添加事件监
听器 ,发送或接收 Notification ,直接改变视图组件的状态。
这样做实现了把视图和控制它的逻辑分离开来。
Controller 与 Command
Controller 保存所有 Command 的映射。Command 类是无状态的,只在需
要时才被创建。
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 5 of 44 5/20/2008 11:17 PM
PureMVC 结构
Controller 与 Command
Command 可以获取 Proxy 对象并与之交互,发送 Notification,执行其他
的 Command。经常用于复杂的或系统范围的操作,如应用程序的“启动”和
“关闭”。应用程序的业务逻辑应该在这里实现。
Façade 与 Core
Façade 类应用单例模式,它负责初始化核心层(Model, View 和
Controller),并能访问它们的 Public 方法。
这样,在实际的应用中,你只需继承 Façade 类创建一个具体的 Façade 类就
可以实现整个 MVC 模式,并不需要在代码中导入编写 Model,View 和
Controller 类。
Proxy、Mediator 和 Command 就可以通过创建的 Façade 类来相互访问通
信。
Observer 与 Notification
PureMVC 的通信并不采用 Flash 的 EventDispatcher/Event ,因为
PureMVC 可能运行在没有 Flash Event 和 EventDispatcher 类的环境中,
它的通信是使用观察者模式以一种松耦合的方式来实现的。
你可以不用关心 PureMVC 的 Observer/Notification 机制是怎么实现的,它
已经在框架内部实现了。你只需要使用一个非常简单的方法从 Proxy,
Mediator, Command 和 Facade 发送 Notification,甚至不需要创建一个
Notification 实例。
Notification可以被用来触发Command的执行
Facade 保存了 Command 与 Notification 之间的映射。当 Notification(通知)被
Administrator
高亮
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 6 of 44 5/20/2008 11:17 PM
PureMVC 结构
Notification可以被用来触发Command的执行
发出时,对应的 Command(命令)就会自动地由 Controller 执行。Command 实
现复杂的交互,降低 View 和 Model 之间的耦合性。
Mediator发送、声明、接收Notification
当用 View 注册 Mediator 时,Mediator 的 listNotifications 方法会被调用,
以数组形式返回该 Mediator 对象所关心的所有 Notification。
之后,当系统其它角色发出同名的 Notification(通知)时,关心这个通知的
Mediator 都会调用 handleNotification 方法并将 Notification 以参数传递到
方法。
Proxy发送,但不接收Notification
在很多场合下 Proxy 需要发送 Notification(通知),比如:Proxy 从远程服
务接收到数据时,发送 Notification 告诉系统;或当 Proxy 的数据被更新时,
发送 Notification 告诉系统。
如果让 Proxy 也侦听 Notification(通知)会导致它和 View(视图)层、
Controller(控制)层的耦合度太高。
View 和 Controller 必须监听 Proxy 发送的 Notification,因为它们的职责是
通过可视化的界面使用户能与 Proxy 持有的数据交互。
不过对 View 层和 Controller 层的改变不应该影响到 Model 层。
例如,一个后台管理程序和一个面向用户程序可能共用一个 Model 类。如果只
是用例不同,那么 View/Controller 通过传递不同的参数就可以共用相同的
Model 类。
Administrator
高亮
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 7 of 44 5/20/2008 11:17 PM
Façade
MVC 元设计模式的核心元素在 PureMVC 中体现为 Model 类、View 类和
Controller 类。为了简化程序开发,PureMVC 应用了 Façade 模式。
Façade 是 Model、View 和 Controller 三者的“经纪人”。实际编写代码时你
并不用导入这三者的类文件,也不用直接使用它们。Façade 类已经在构造方法包
含了对核心 MVC 三者单例的构造。
一般地,实际的应用程序都有一个 Façade 子类,这个 Façade 类对象负责初始
化 Controller(控制器),建立 Command 与 Notification 名之间的映射,并执
行一个 Command 注册所有的 Model 和 View。
具体Façade是什么样子的?
Façade 类应被当成抽象类, 永远不被直接实例化。针对具体的应用程序,你应
该具体编写 Façade 的子类,添加或重写 Façade 的方法来实现具体的应用。
按照惯例,这个类命名为“ApplicationFacade”(当然,命名随你喜欢),
如前所述,它主要负责访问和通知 Command,Mediator 和 Proxy。
通常,不同的运行平台都会创建视图结构,尽管创建过程不一样。(比如 Flex
中 MXML 程序负责实例化所有子视图组件,Flash 影片在 Stage 上构建可视
对象)。视图结构构建完毕时,整个 PureMVC 机制也已经安置妥当。
创建的 Facade 子类也被用来简化“启动”的过程。应用程序调用 Facade 子
类的 startup 方法,并传递自身的一个引用即完成启动,使得应用程序不需要
过多了解 PureMVC。
为程序创建Façade
Façade 类的
内容
财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容
很简单。思考下面的例子:
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 8 of 44 5/20/2008 11:17 PM
Façade
为程序创建Façade
ApplicationFacade.as:
package com.me.myapp
{
import org.puremvc.as3.interfaces.*;
import org.puremvc.as3..patterns.facade.*;
import com.me.myapp.view.*;
import com.me.myapp.model.*;
import com.me.myapp.controller.*;
// MyApp 程序的 Façade 类
public class ApplicationFacade extends Façade implements IFacade
{
//定义 Notification(通知)常量
public static const STARTUP:String = "startup";
public static const LOGIN:String = "login";
//得到 ApplicationFacade 单例的工厂方法
public static function getInstance() : ApplicationFacade
{
if ( instance == null ) instance = new ApplicationFacade( );
return instance as ApplicationFacade;
}
//注册 Command,建立 Command 与 Notification 之间的映射
override protected function initializeController( ) : void
{
super.initializeController();
registerCommand( STARTUP, StartupCommand );
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 9 of 44 5/20/2008 11:17 PM
Façade
为程序创建Façade
registerCommand( LOGIN, LoginCommand );
registerCommand( LoginProxy.LOGIN_SUCCESS,
GetPrefsCommand );
}
//启动 PureMVC,在应用程序中调用此方法,并传递应用程序本身的引用
public function startup( app:MyApp ) : void
{
sendNotification( STARTUP, app );
}
}
}
上述代码需要注意以下几点:
o ApplicationFacade 继承自 PureMVC 的 Façade 类,Façade
类实现了 IFacade 接口。
o 这个例子里 ApplicationFacade 没有重写构造方法 。如果重写
构造方法,应该在构造方法里先调用父类的构造方法。
o 类方法 getInstance 用于返回 ApplicationFacade 的单例,并
将实例保存在父类的一个 protect 变量中。在返回该实例之前必
须先把它转化为 ApplicationFacade 类型。
o 定义了 Notification 名称常量。Façade 类是整个系统其他角色相互
访问通信的核心,所以在这里定义 Notification(通知)名称常量
是最合适的。
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 10 of 44 5/20/2008 11:17 PM
Façade
为程序创建Façade
o 初始化 Controller(控制器),并建立 Command 与 Notification 之
间的映射,当 Notification(通知)发出时相关的 Command(命
令)就会被执行。
o 提供一个带有应用程序类型参数的 startup 方法,该参数能过
Notification 传递到 StartupCommand。
实现这些只需要继承父类很少的功能。
初始化Façade
PureMVC 的 Façade 类在构造方法中初始化了 Model、View 和
Controller 对象,并把对它们的引用保存在成员变量。
这样,Façade 就可以访问 Model、View 和 Controller 了。这样把对核心
层的操作都集中在 Façade,避免开发者直接操作核心层。
那么,在具体的应用程序中,Façade 是何时何地初始化的呢?请查看下面的
Flex 代码:
MyApp.mxml:
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
:
哪些代码应该放在哪里?确切的说,Command 应该做什么?
程序中的逻辑分为 Business Logic(业务逻辑)和 Domain Logic(域逻
辑),首先需要知道这两者之间的差别。
Command 管理应用程序的 Business Logic(业务逻辑),与 Domain
Logic(域逻辑)相区别,Business Logic(业务逻辑)要协调 Model 与视
图状态。
Model 通过使用 Proxy 来保证数据的完整性、一致性 。Proxy 集中程序的
Domain Logic(域逻辑),并对外公布操作数据对象的 API。它封装了所
有对数据模型的操作,不管数据是客户端还是服务器端的,对程序其他部分
来说就是数据的访问是同步还是异步的。
Command 可能被用于实现一些复杂、必须按照一定顺序的系统行为,上一步动
作的结果可能会流入一下个动作。.
Mediator 和 Proxy 可以提供一些操作接口让 Command 调用来管理 View
Component 和 Data Object,同时对 Command 隐藏具体操作的细节。
Administrator
高亮
Administrator
高亮
Administrator
高亮
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 17 of 44 5/20/2008 11:17 PM
Command
复杂的操作与业务逻辑
我们这里谈论的 View Component 时就是指像按钮这种用户直接交互的小
东西。而 Data Object 则是指能以任意结构存储数据的对象。
Command 与 Mediator 和 Proxy 交互,应避免 Mediator 与 Proxy 直接交互。请看
下面这个用于程序“启动”的 Command:
StartupCommand.as:
package com.me.myapp.controller
{
import org.puremvc.as3.interfaces.*;
import org.puremvc.as3.patterns.command.*;
import com.me.myapp.controller.*;
// 开 时执程序 始 行的 MacroCommand.
public class StartupCommand extends MacroCommand
{
//添加子 Command 初始化 MacroCommand.
override protected function initializeMacroCommand() : void
{
addSubCommand( ModelPrepCommand );
addSubCommand( ViewPrepCommand );
}
}
}
这是一个添加了两个子 Command 的 MacroCommand,执行时两个版子命令会
按照“先进先出”(FIFO)的顺序被执行。
Administrator
高亮
Command与mediator和proxy交互,应避免Mediator与Proxy直接交互
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 18 of 44 5/20/2008 11:17 PM
Command
复杂的操作与业务逻辑
这个复合命令定义了 PureMVC 在“开启”(startup)时的动作序列。但具体
的,我们应该做什么?按照什么顺序?
在用户与数据交互之前,Model 必须处于一种一致的已知的状态。一旦
Model 初始化完成,视图就可以显示数据允许用户操作与之交互。
因此,一般“开启”(startup)过程有两个主要的动作:Model 初始化与 View 初
始化。
ModelPrepCommand.as:
package com.me.myapp.controller
{
import org.puremvc.as3.interfaces.*;
import org.puremvc.as3.patterns.observer.*;
import org.puremvc.as3.patterns.command.*;
import com.me.myapp.*;
import com.me.myapp.model.*;
//创建 Proxy 对象,并注册。
public class ModelPrepCommand extends SimpleCommand
{
//由 MacroCommand 调用
override public function execute( note : INotification ) : void
{
facade.registerProxy( new SearchProxy() );
facade.registerProxy( new PrefsProxy() );
facade.registerProxy( new UsersProxy() );
}
PureMVC 是 Futurescale 公司创建并维护的开源自由的程序框架。Futurescale, Inc. Copyright © 2006-08, Some rights
reserved。使用 PureMVC 必须遵守美国 Creative Commons 3.0 Attribution 协议。PureMVC、本文档以及任何从
Futurescale 网站下载的文档、培训资料及示例代码,都不提供任何明示或者默示的担保,包括但是不限于是否符合特定的
目的、未侵害他人权利的担保。
Page 19 of 44 5/20/2008 11:17 PM
Command
复杂的操作与业务逻辑
}
}
Model 的初始化通常比较简单:创建并注册在“开启”过程中需要用到的
Proxy。
上面这个 ModelPrepCommand 类是一个 SimpleCommand 例子,它功
能就是初始化 Model,它是前面那个 MacroCommand 的第一个子命令,
所以它会最先被执行。
通常具体的 Façade 对象,它创建并注册了多个在“启动”(startup)过程
中会用到的 Proxy 类。注意这里 Command 并没有操作或初始任何的
Model 数据。Proxy 的职责才是取得,创建,和初始化数据对象。
ViewPrepCommand.as:
package com.me.myapp.controller
{
import org.puremvc.as3.interfaces.*;
import org.puremvc.as3.patterns.observer.*;
import org.puremvc.as3.patterns.command.*;
import com.me.myapp.*;
import com.me.myapp.vi