天天看点

有关于as3的puremvc框架实现和理解

今天学习PureMVC,看了教程,写了Demo,记录并分享学习过程。

教程参考:http://puremvc.org/component/option,com_wrapper/Itemid,183/

PureMVC使用观察者模式,将代码分离为三个离散的层:模式、视图和控制器,这三部分由三个单例模式类管理,分别是Model、View和Controller,三者合称为核心层或核心角色。PureMVC中还有另外一个单例模式类——Façade,Façade提供了与核心层通信的唯一接口,以简化开发复杂度。

PureMVC的通信不采用Flash的EventDispatcher/Event,是因为PureMVC可能运行在没有FlashEvent和EventDispatcher类的环境中。

PureMVC架构示意图:

由图很明显可以知道PureMVC的层次结构:

  1. Model层:由Value Object和Proxy组成。Proxy负责操作数据模型,与远程服务通信存取数据。Proxy发送Notification,但不接收Notification,比如Proxy从远程服务接收到数据或数据被更新时,都要发送Notification告诉系统,由View层和Controller层来接收并做相应反馈到界面。
  2. View层:由UI和对应的Mediator组成。Mediator保存一个或多个View Component的引用,通过View Component自身提供的API管理它们。Mediator既能发送Notification也能接受Notification,主要职责是处理View Component派发的事件和系统其它部分发出来的Notification(通知)。
  3. Controller层:由Command和Facade组成。Command实现应用程序的业务逻辑。可以获取Proxy对象并与之交互,发送Notification,执行其它的Command。用于复杂的或系统范围的操作,如应用程序的“启动”和“关闭”。Command接收通知也可以发出通知。实际Command类可以继承自SimpleCommand(对于单独业务),也可以继承自MacroCommand(如果需要执行多个业务逻辑)。Facade类应用单例模式,负责初始化核心层(Model,View和Controller),并能访问它们的public方法。在实际的应用中,只需要继承Facade类创建一个具体的Facade类(一般命名为ApplicationFacade)就可以实现整个的MVC模式,并不需要在代码中导入编写Model,View和Controller的类。

Facade和Proxy只能发送Notification,Mediator既可以发送也可以接收Notification,Notification被映射到Command,同时Command也可以发送Notification,这是一种“发布/订阅”机制,所有的观察者都可以收到相同的通知。例如多个书刊订阅者可以订阅同一份杂志,当杂志有新刊物出版时,所有的订阅者都会被通知。

下面开始写例子PureMVCDemo:完成用户登录在后台进行验证合法性,并反馈给前台。

版本说明:

Flex:Flex4

ActionScript:ActionScript 3.0

Java JDK:jdk1.6.0_20

PureMVC:PureMVC_AS3_2_0_4,官方网站提供多种语言的资源包下载,在这里用ActionScript版本,下载链接http://trac.puremvc.org/PureMVC_AS3/。将下载到的资源文件PureMVC_AS3_2_0_4.swc拷贝到Flex工程的libs目录下即可。

工具及环境和Java后台服务应用的建立过程介绍:详见我的上篇文章,BlazeDS实现Flex和Java通信的Demo

1、后台Java服务端项目工程PureMVCDemo组成:

相应代码:

UserVO.java

package net.dreamhui.java;

public class UserVO {

         publicString userName;

         publicString passWord;

         publicUserVO()

         {

                  //和ActionScript对应得构造方法

         }

         //getters& setters

         publicString getUserName() {

                  returnuserName;

         }

         publicvoid setUserName(String userName) {

                  this.userName= userName;

         }

         publicString getPassWord() {

                  returnpassWord;

         }

         publicvoid setPassWord(String passWord) {

                  this.passWord= passWord;

         }

}

LoginUser.java

package net.dreamhui.java;

public class LoginUser {

         publicUserVO currentUser;

         privateString uName;

         privateString pWord;

         //Flex端要调用的服务

         publicUserVO login(UserVO par_user)

         {

                  //UserVOpar_user2 = UserVO(par_user);

                  uName= par_user.userName;

                  pWord= par_user.passWord;

                  if(uName.equalsIgnoreCase("wwh")&&pWord.equalsIgnoreCase("wwh"))

                  {

                          returnpar_user;

                          //return"欢迎用户:"+uName;

                  }

                  else{

                          returnnull;

                          //return"用户名或密码错误,请重新输入";

                  }

         }

}

配置文件remoting-config.xml要添加的内容:

<destinationid="loginUser">

                  <properties>

                          <source>net.dreamhui.java.LoginUser</source>

                  </properties>

</destination>

2,前台Flex工程PureMVCDemo工程组成:

相应代码(按照开发流程):

LoginPanel.mxml

<?xml version="1.0"encoding="utf-8"?>

<s:Panelxmlns:fx="http://ns.adobe.com/mxml/2009"

         xmlns:s="library://ns.adobe.com/flex/spark"

         xmlns:mx="library://ns.adobe.com/flex/mx"

         title="请登陆"currentState="initState"

         creationComplete="lvcreationComplete(event)">

         <!--~~~~~~~~~~~~~~~~~~~~~~Script~~~~~~~~~~~~~~~~~~~~~~-->

         <fx:Script>

                  <![CDATA[

                          importmx.controls.Alert;

                          importmx.core.UIComponent;

                          importmx.events.FlexEvent;

                          importmx.events.ValidationResultEvent;

                          importmx.rpc.events.FaultEvent;

                          importmx.rpc.events.ResultEvent;

                          importmx.validators.Validator;

                          importnet.dreamhui.controller.events.LoginEvent;

                          importnet.dreamhui.model.vo.UserVO;

                          privatevar validObjs:Array;

                          [Bindable]

                          privatevar _currUser:UserVO;// = new UserVO();

                          protectedfunction lvcreationComplete(event:FlexEvent):void

                          {

                                   validObjs= [unSV,pwSV];

                          }

                          protectedfunction submit(event:MouseEvent):void

                          {

                                   varvalidatorResults:Array;

                                   validatorResults= Validator.validateAll(validObjs);

                                   if(validatorResults.length== 0)

                                   {

                                            varuser:UserVO = new UserVO();

                                            user.userName= uName.text;

                                            user.passWord= pWord.text;

                                            var lgEvent:LoginEvent= new LoginEvent(LoginEvent.LOGIN_USER);

                                            lgEvent.data= user;

                                            dispatchEvent(lgEvent);

                                            //Alert.show("dispatchEvent");

                                            //派发事件

                                            }

                                   else

                                   {

                                            //定义校验出错事件

                                            varvEvent:ValidationResultEvent;

                                            //取出第一个出错事件

                                            vEvent= validatorResults[0] as ValidationResultEvent;

                                            //将光标定位到第一个出错的组件上

                                            (vEvent.target.sourceas UIComponent).setFocus();

                                   }

                          }

                          [Bindable]

                          publicfunction get currUser():UserVO

                          {

                                   return_currUser;

                          }

                          publicfunction set currUser(value:UserVO):void

                          {

                                   _currUser= value;

                          }

                  ]]>

         </fx:Script>

         <!--~~~~~~~~~~~~~~~~~~~~~~states~~~~~~~~~~~~~~~~~~~~~~-->

         <s:states>

                  <s:Statename="initState"/>

                  <s:Statename="loginState"/>

         </s:states>

         <!--~~~~~~~~~~~~~~~~~~~~~~Declarations~~~~~~~~~~~~~~~~~~~~~~-->

         <fx:Declarations>

                  <!--定义用户名和密码的输入校验类-->

                  <mx:StringValidatorid="unSV"

                          source="{uName}"

                          property="text"

                          required="true"

                          maxLength="10"

                          tooLongError="用户名最长为10位"

                          requiredFieldError="请填写用户名"/>

                  <mx:StringValidatorid="pwSV"

                          source="{pWord}"

                          property="text"

                          required="true"

                          maxLength="10"

                          tooLongError="密码最长为10位"

                          requiredFieldError="请填写密码"/>

         </fx:Declarations>

         <!--~~~~~~~~~~~~~~~~~~~~~~UIComponents~~~~~~~~~~~~~~~~~~~~~~-->

         <mx:FormincludeIn="initState">

                  <mx:FormItemlabel="用户名" >

                          <s:TextInputid="uName" />

                  </mx:FormItem>

                  <mx:FormItemlabel="密码" >

                          <s:TextInputid="pWord" displayAsPassword="true" />

                  </mx:FormItem>

                  <mx:FormItem>

                          <s:Buttonid="submitBtn" click="submit(event)"  label="登陆"right="0" />

                  </mx:FormItem>

         </mx:Form>

         <s:HGroupincludeIn="loginState" top="20" left="10" >

                  <s:Label  text="欢迎尊贵的用户:"/>

                  <s:Label  id="cuName" text="{currUser.userName}"/>

         </s:HGroup>

</s:Panel>

UserVO.as

package net.dreamhui.model.vo

{

         [Bindable]

         [RemoteClass(alias="net.dreamhui.java.UserVO")]

         publicclass UserVO

         {

                  privatevar _userName:String;

                  privatevar _passWord:String;

                  publicfunction UserVO()

                  {

                  }

                  //getters& setters

                  publicfunction get userName():String

                  {

                          return_userName;

                  }

                  publicfunction set userName(value:String):void

                  {

                          _userName= value;

                  }

                  publicfunction get passWord():String

                  {

                          return_passWord;

                  }

                  publicfunction set passWord(value:String):void

                  {

                          _passWord= value;

                  }

         }

}

LoginEvent.as

package net.dreamhui.controller.events

{

         importflash.events.Event;

         publicclass LoginEvent extends Event

         {

                  privatevar _data:Object;

                  publicstatic const LOGIN_USER:String = "loginUser";

                  publicfunction LoginEvent(type:String, bubbles:Boolean=false,cancelable:Boolean=false)

                  {

                          super(type,bubbles, cancelable);

                  }

                  publicfunction get data():Object

                  {

                          return_data;

                  }

                  publicfunction set data(value:Object):void

                  {

                          _data= value;

                  }

         }

}

LoginPanelMediator.as

package net.dreamhui.view

{

         importnet.dreamhui.controller.ApplicationFacade;

         importnet.dreamhui.controller.events.LoginEvent;

         importnet.dreamhui.model.LoginProxy;

         importnet.dreamhui.model.vo.UserVO;

         importnet.dreamhui.view.ui.LoginPanel;

         importmx.controls.Alert;

         importorg.puremvc.as3.interfaces.IMediator;

         importorg.puremvc.as3.interfaces.INotification;

         importorg.puremvc.as3.patterns.mediator.Mediator;

         publicclass LoginPanelMediator extends Mediator implements IMediator

         {

                  publicstatic const NAME:String = "LoginPanelMediator";

                  publicfunction LoginPanelMediator(viewComponent:LoginPanel)

                  {

                          super(NAME,viewComponent);

                          viewComponent.addEventListener(LoginEvent.LOGIN_USER,login);

                          //添加视图事件监听,当点击“登录”按钮时触发

                  }

                  publicfunction login(event:LoginEvent):void

                  {

                          //Alert.show("LoginPanelMediatorlogin");

                          varlgUser:UserVO = event.data as UserVO;

                          sendNotification(ApplicationFacade.USER_LOGIN,lgUser);

                  }

                  overridepublic function listNotificationInterests():Array

                  {

                          return[LoginProxy.LOGIN_YES,LoginProxy.LOGIN_NO];

                  }

                  overridepublic function handleNotification(notification:INotification):void

                  {

                           switch(notification.getName())

                          {

                                   caseLoginProxy.LOGIN_YES:

                                            //通知来源LoginProxy,如果用户名和密码正确

                                            loginPanel.currUser= notification.getBody() as UserVO;

                                            loginPanel.currentState= "loginState";

                                            break;

                                   caseLoginProxy.LOGIN_NO:

                                            //通知来源LoginProxy,如果用户名或密码错误或远程服务调用失败

                                            //Alert.show("用户名或密码错误,请重新填写");

                                            Alert.show(notification.getBody().toString());

                          }

                  }

                  protectedfunction get loginPanel():LoginPanel

                  {

                          returnviewComponent as LoginPanel;

                  }

         }

}

LoginCommand.as

package net.dreamhui.controller.business

{

         importnet.dreamhui.model.LoginProxy;

         importnet.dreamhui.model.vo.UserVO;

         importmx.controls.Alert;

         importorg.puremvc.as3.interfaces.INotification;

         importorg.puremvc.as3.patterns.command.SimpleCommand;

         publicclass LoginCommand extends SimpleCommand

         {

                  overridepublic function execute(notification:INotification):void

                  {

                          //Alert.show("LoginCommandexecute");

                          varlgUser:UserVO = notification.getBody() as UserVO;

                          //获取通知携带参数,类型为Object,转换为需要的类型

                          varlgProxy:LoginProxy = facade.retrieveProxy(LoginProxy.NAME) as LoginProxy;

                          //检索到负责远程过程调用的业务代理LoginProxy

                          lgProxy.userLogin(lgUser);

                           //调用远程过程,对调用过程的结果处理,在LoginProxy里面

                  }

         }

}

LoginProxy.as

package net.dreamhui.model

{

         importmx.rpc.events.FaultEvent;

         importmx.rpc.events.ResultEvent;

         importmx.rpc.remoting.RemoteObject;

         importmx.controls.Alert;

         importnet.dreamhui.model.vo.UserVO;

         importorg.puremvc.as3.interfaces.IProxy;

         importorg.puremvc.as3.patterns.proxy.Proxy;

         publicclass LoginProxy extends Proxy implements IProxy

         {

                  publicstatic const NAME:String = "LoginProxy";

                  publicstatic const LOGIN_YES:String = "loginYes";

                  publicstatic const LOGIN_NO:String = "loginNo";

                  //声明常量,避免手误导致编译运行错误

                  privatevar loginService:RemoteObject;

                  publicfunction LoginProxy()

                  {

                          super(NAME,new UserVO());

                          loginService= new RemoteObject();

                          loginService.destination= "loginUser";

                          //初始化远程过程调用的RemoteObject实例

                          loginService.addEventListener(FaultEvent.FAULT,onFault);

                          loginService.login.addEventListener(ResultEvent.RESULT,onResult);

                          //给远程过程调用添加事件监听,在监听函数里对调用返回结果做处理

                  }

                  publicfunction userLogin(par_U:UserVO):void

                  {

                          //Alert.show("LoginProxyuserLogin");

                          loginService.login(par_U);

                          //调用服务端的业务处理方法

                  }

                  protectedfunction onFault(event:FaultEvent):void

                  {

                          //Alert.show("onFault");

                          sendNotification(LOGIN_NO,event.fault.faultDetail);

                  }

                  protectedfunction onResult(event:ResultEvent):void

                  {

                          //Alert.show("onResult");

                          if(event.resultas UserVO == null)

                          {

                                   //返回null,调用成功,但拒绝登陆成功,发出通知LOGIN_NO

                                   sendNotification(LOGIN_NO,"用户名或密码错误,请重新输入");

                          }

                          else

                          {

                                   //返回正常UserVO,调用成功,登陆成功,发出通知LOGIN_YES

                                   sendNotification(LOGIN_YES,event.resultas UserVO);

                          }

                  }

         }

}

ApplicationFacade.as

package net.dreamhui.controller

{

         importorg.puremvc.as3.interfaces.IFacade;

         importorg.puremvc.as3.patterns.facade.Facade;

         importnet.dreamhui.controller.business.StartupCommand;

         importnet.dreamhui.controller.business.LoginCommand;

         publicclass ApplicationFacade extends Facade implements IFacade

         {

                  publicstatic const STARTUP:String = "startUp";

                  publicstatic const USER_LOGIN:String = "userLogin";

                  publicstatic function getInstance():ApplicationFacade

                  {

                          if(instance== null)

                          {

                                   instance= new ApplicationFacade();

                          }

                          returninstance as ApplicationFacade;

                  }

                  overrideprotected function initializeController():void

                  {

                          super.initializeController();

                          registerCommand(STARTUP,StartupCommand);

                          registerCommand(USER_LOGIN,LoginCommand);

                  }

                  publicfunction startup(app:PureMVCDemo):void

                  {

                          sendNotification(STARTUP,app);

                  }

         }

}

StartupCommand.as

package net.dreamhui.controller.business

{

         importorg.puremvc.as3.patterns.command.MacroCommand;

         publicclass StartupCommand extends MacroCommand

         {

                  overrideprotected function initializeMacroCommand():void

                  {

                          addSubCommand(ModelPreCommand);

                          addSubCommand(ViewPreCommand);

                  }

         }

}

ModelPreCommand.as

package net.dreamhui.controller.business

{

         importnet.dreamhui.model.LoginProxy;

         importorg.puremvc.as3.interfaces.INotification;

         importorg.puremvc.as3.patterns.command.SimpleCommand;

         importorg.puremvc.as3.patterns.observer.*;

         publicclass ModelPreCommand extends SimpleCommand

         {

                  overridepublic function execute(notification:INotification):void

                  {

                          facade.registerProxy(newLoginProxy());

                          //注册应用程序所需要的Proxy

                  }

         }

}

ViewPreCommand.as

package net.dreamhui.controller.business

{

         importnet.dreamhui.view.ApplicationMediator;

         importnet.dreamhui.view.LoginPanelMediator;

         importnet.dreamhui.view.ui.LoginPanel;

         importorg.puremvc.as3.interfaces.INotification;

         importorg.puremvc.as3.patterns.command.SimpleCommand;

         publicclass ViewPreCommand extends SimpleCommand

         {

                  overridepublic function execute(notification:INotification):void

                  {

                          //注册应用程序的View视图和对应的Mediator

                          varapp:PureMVCDemo = notification.getBody() as PureMVCDemo;

                          facade.registerMediator(newApplicationMediator(app));

                          varlgP:LoginPanel = app.getElementAt(0) as LoginPanel;

                          facade.registerMediator(newLoginPanelMediator(lgP));

                  }

         }

}

PureMVCDemo.mxml

<?xml version="1.0"encoding="utf-8"?>

<s:Applicationxmlns:fx="http://ns.adobe.com/mxml/2009"

         xmlns:s="library://ns.adobe.com/flex/spark"

         xmlns:mx="library://ns.adobe.com/flex/mx"

         minWidth="955"minHeight="600"

         xmlns:ui="net.dreamhui.view.ui.*"

         creationComplete="{facade.startup(this);}">

         <!--~~~~~~~~~~~~~~~~~~~~~~~~Script~~~~~~~~~~~~~~~~~~~~~~~~-->

         <fx:Script>

                  <![CDATA[

                          importmx.controls.Alert;

                          importnet.dreamhui.controller.ApplicationFacade;

                          //声明并实例化控制器ApplicationFacade

                          privatevar facade:ApplicationFacade = ApplicationFacade.getInstance();

                  ]]>

         </fx:Script>

         <!--~~~~~~~~~~~~~~~~~~~~~~~~UIComponents~~~~~~~~~~~~~~~~~~~~~~~~-->

         <ui:LoginPanelid="lgPanel" width="340" height="200"top="20"

                  horizontalCenter="-30"  fontSize="20" />

</s:Application>

ApplicationMediator.as

package net.dreamhui.view

{

         importorg.puremvc.as3.interfaces.IMediator;

         importorg.puremvc.as3.patterns.mediator.Mediator;

         publicclass ApplicationMediator extends Mediator implements IMediator

         {

                  publicstatic const NAME:String = "ApplicationMediator"

                  publicfunction ApplicationMediator(viewComponent:PureMVCDemo)

                  {

                          super(NAME,viewComponent);

                  }

         }

}

上一篇: AS3 事件流
下一篇: as3 时间