今天学习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();

}

}

/**~~~~~~~~~~~~~~~~~~~getters& setters~~~~~~~~~~~~~~~~~~~**/

[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;

/**

* 为了实现远程Class之间的绑定,构造方法必须形式上完全一致,

* 包括参数的个数和类型,否则会出现异常。

* */

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);

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

}

/**

* 处理事件监听,Mediator发送通知,递交给Command处理业务

* */

publicfunction login(event:LoginEvent):void

{

//Alert.show("LoginPanelMediatorlogin");

varlgUser:UserVO = event.data as UserVO;

sendNotification(ApplicationFacade.USER_LOGIN,lgUser);

/**

* 发送通知USER_LOGIN并携带参数UserVO对象lgUser

* 在ApplicationFacade中registerCommand(USER_LOGIN,LoginCommand);

* 该句将ApplicationFacade.USER_LOGIN注册给LoginCommand,当通知被发出后,

* 将转向执行LoginCommand的excute方法

* */

}

/**

* 注册该Mediator感兴趣的通知Notification,以数组形式返回

* */

overridepublic function listNotificationInterests():Array

{

return[LoginProxy.LOGIN_YES,LoginProxy.LOGIN_NO];

}

/**

* 处理感兴趣的Notification,即根据通知,操作View视图的属性、状态等;

* 此处的通知来源可以是本身、其他的Mediator或Command或Proxy,所有能发出通知的地方

* */

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;

/**

* 因为LoginCommand只处理一个单一业务,即调用后台Java程序,返回

* 用户名和密码的匹配正确与否,所以继承自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的puremvc框架实现和理解相关推荐

  1. Unity实战(3):pureMVC框架应用

    目录 前言 一.下载框架并编译生成dll文件 二.Unity搭建基本要素 三.pureMVC简要说明 四.pureMVC脚本编写 4.1 MyData脚本 4.2 MyDataProxy脚本 4.3 ...

  2. 什么是 PureMVC 框架(提供下载)

    PureMVC是在基础的经典模型.视图和控制器上建立的一个轻量级的应用框架,这种开源框架是免费的,它最初是执行的ActionScript 3语言使用的Adobe Flex.Flash和AIR,现在已经 ...

  3. 解读PureMVC框架

    作者:吴秦 出处:http://www.cnblogs.com/skynet/ 本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). 参考 ...

  4. [Unity]PureMVC框架解读(上)

    PureMVC框架解读 简易UI框架 1.UI框架核心方法 BaseUI会记录UI的名字(枚举)和Controller用来将UI与具体操作方法解耦 UIManger利用字典记录所有的UI组件,然后提供 ...

  5. PureMVC框架应用简述

    一.介绍 PureMVC是基于MVC思想建立的一个轻量级的应用框架,这套框架有多种语言的版本 ActionScript 2 ActionScript 3 C++ C# ColdFusion Dart ...

  6. PureMVC框架的学习笔记

    曾经自己做的项目UI层使用简单的UI框架,发现扩展性不强,大型项目多人协同也是个问题,于是学习了比较经典的基于MVC的PureMVC以及基于MVVM的LoxodonFramework,今天记录一下有关 ...

  7. Unity PureMVC框架案例

    引言 PureMVC框架解读上:https://blog.csdn.net/qq_29579137/article/details/73692842 PureMVC框架解读下:https://blog ...

  8. QT 版puremvc框架

    PDMvcFramework MVC介绍 MVC框架 将应用程序分为Model.View.Controller三个大模块,Model主要负责应用程序的数据持有,View模块负责业务UI展示,Contr ...

  9. Flash WebGame 开发经验心得和PureMVC框架细说(转载)

    →前端的主程序架构和模块划分与人手和人事分工是紧密联系在一起的,而这些很大程度上又是由项目本身决定的.纵观现在国内绝大多数FLASH WEB GAME的规模和难度,我觉得前端AS人员大概需要2-7个之 ...

最新文章

  1. Centos7状态下查看防火墙状态及修改服务端口
  2. Ptyhon学习之元组
  3. C#几种在客户端跳转
  4. 【转】iPython入门技巧
  5. 使用Spark Streaming SQL基于时间窗口进行数据统计
  6. CVPR2020 夜间目标检测挑战赛冠军方案解读
  7. 罗永浩:交个朋友直播间单日支付金额突破1亿元
  8. Linux驱动:VFIO概述(vfio/iommu/device passthrough)
  9. python如何使用多线程_Python多线程与多线程中join()的用法
  10. 【恋上数据结构】插入排序及二分搜索优化
  11. Mac OS 区块链hyperledger环境搭建、环境架构介绍、环境如何用、部署 Chaincode、智能合约的调用
  12. 【Flex】FLEX工程合并留意错误。
  13. ESP-Drone控制板设计的第二个任务-绘制USB-TTL串口下载电路和ESP32-S2芯片内置USB接口电路
  14. Word 2016 插入尾注之后删除方法
  15. 一键设置 DeviceAdmin/ProfileOwner/DeviceOwner 应用
  16. Linux程序包管理命令之rpm
  17. Domoticz-Dummy(虚拟传感器)
  18. Windows 11的这19个新功能,你都知道吗?
  19. 小程序个人中心页面,模块入口搭建
  20. HTML中的format函数是干嘛的,css format是什么意思?

热门文章

  1. Intel8251可编程串行扩展
  2. 可穿戴式计算机技术,可穿戴式无线网络技术方案详解(一)
  3. 【HDOJ】1017 A Mathematical Curiosity_天涯浪子_新浪博客
  4. 双链笔记葫芦笔记综合评测:优点、缺点、建议
  5. 2M电路故障检测—专业设备TFN LT30 2M误码仪
  6. 科赫曲线及科赫雪花的画法
  7. 用python语言自我介绍_使用Python实现自我介绍
  8. 29日全国铁路预计发送旅客978万人次 同比增长4%
  9. 一篇带你揭开 go mod 的面纱
  10. 行为驱动python