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类是无状态的,只在需要时才被创建。

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(通知)被发出时,对应的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类。


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类的内容很简单。思考下面的例子:
 1package com.me.myapp
 2{
 3import org.puremvc.as3.interfaces.*;
 4import org.puremvc.as3..patterns.facade.*;
 5import com.me.myapp.view.*;
 6import com.me.myapp.model.*;
 7import com.me.myapp.controller.*;
 8// MyApp程序的Façade类
 9public class ApplicationFacade extends Façade implements IFacade
10{
11//定义Notification(通知)常量
12public static const STARTUP:String = "startup";
13public static const LOGIN:String = "login";
14//得到ApplicationFacade单例的工厂方法
15public static function getInstance() : ApplicationFacade
16{
17if ( instance == null ) instance = new ApplicationFacade( );
18return instance as ApplicationFacade;
19}

20//注册Command,建立Command与Notification之间的映射
21override protected function initializeController( ) : void
22{
23super.initializeController();
24registerCommand( STARTUP, StartupCommand );
25registerCommand( LOGIN, LoginCommand );
26registerCommand( LoginProxy.LOGIN_SUCCESS, GetPrefsCommand );
27}

28//启动PureMVC,在应用程序中调用此方法,并传递应用程序本身的引用 public function startup( app:MyApp ) : void
29{
30sendNotification( STARTUP, app );
31}

32}

33}


上述代码需要注意以下几点:
oApplicationFacade继承自PureMVC的Façade类,Façade类实现了IFacade接口。

o这个例子里ApplicationFacade没有重写构造方法。如果重写构造方法,应该在构造方法里先调用父类的构造方法。

o类方法getInstance用于返回ApplicationFacade的单例,并将实例保存在父类的一个protect变量中。在返回该实例之前必须先把它转化为ApplicationFacade类型。

o定义了Notification名称常量。Façade类是整个系统其他角色相互访问通信的核心,所以在这里定义Notification(通知)名称常量是最合适的。

o初始化Controller(控制器),并建立Command与Notification之间的映射,当Notification(通知)发出时相关的Command(命令)就会被执行。

o提供一个带有应用程序类型参数的startup方法,该参数能过Notification传递到StartupCommand。