最简单易理解的Flex PureMVC入门例子:实现登录

在PureMVC 学习笔记(一)中介绍了一个《flex框架pureMVC的使用:第一步》(后简称:第一步)的例子,此文关于PureMVC的介绍非常生动明了,如果想快速学习PureMVC这个framework的话,建议看一下。

不过其中所举例子对于想要自己动手使用PureMVC的人就稍显不足了。因为《第一步》对于代码的介绍是从application启动加载Facade开始的,然后注册Command,Proxy,Mediator,这样的说明的好处是快速让读者理解PureMVC内部运行机制。在理解了PureMVC的原理之后,我们就要开始构思怎样对一个工程应用PureMVC,谨以一个登录的例子,说明如何使用PureMVC构建工程,工程结构图如下:

因为所有的 Mediator、Proxy、Command、Event 的名称都被我定义在system包下的NameSpace.as中,所以先看给出此as的代码:

package system
{

 public class NameSpace
 {
  public static const LoginProxyName:String=”LoginProxy”;
  public static const LoginSuccess:String=”loginSuccess”;
  public static const LoginFailed:String=”loginFailed”;
  public static const LoginEvent:String=”loginEvent”;
  public static const LoginMediatorName:String=”loginMediator”;
  public static const ApplicationLogin:String=”login”;
  public static const ApplicationMediatorName:String=”appliactionMediator”;
  public static const FacadeStart:String=”start”;
 }
}

Model和Proxy

因为数据来自Model层,我们用Proxy进行管理,所以我们先来设计这一模块,定义LoginVO这样一个简单的数据结构,用于存储登录的数据:用户名和密码。代码如下:

package model.vo
{
 public class LoginVO
 {
  public var username:String;
  public var password:String;
 }
}

 接着建立LoginProxy,需要继承Proxy实现IProxy:

package model
{
 import model.vo.LoginVO;
 import org.puremvc.as3.interfaces.IProxy;
 import org.puremvc.as3.patterns.proxy.Proxy;
 import system.NameSpace;

 public class LoginProxy extends Proxy implements IProxy
 {
  public function LoginProxy()
  {
   super(NameSpace.LoginProxyName);
  }

  public function CheckLogin(vo:LoginVO):void
  {
   if (vo.username == “test” && vo.password == “test”)
   {
    sendNotification(NameSpace.LoginSuccess, vo);
   }
   else
   {
    sendNotification(NameSpace.LoginFailed);
   }
  }
 }
}

每一个Proxy都需要有自己的名称,为了便于统一的管理,我把所有的Name都定义在NameSpace中,这样做的好处是有利于协作开发,同时也有助于程式的调试。从代码中可以看到,整个Model与外界没什么联系,提供了一个CheckLogin()方法,根据判断的结果发送通知。至于这样的通知发送出去谁来处理,怎么处理,就不是Proxy关心的事了。由此可知,Proxy的耦合度相当低!(感觉PureMVC这个组织里,Facade是老大,管着手下三个小弟:Proxy、Mediator、Command,这三个家伙都是各干各的,从不互相帮助,各人自扫门前雪,真是selfish)

View 和 Mediator

任何一个应用都有和用户交互的界面,将这些界面统一起来进行管理,就是PureMVC的View层。在View层内,实现界面的管理委托给了Mediator,Mediator负责管理应用界面的数据更新和提交数据。当用户界面发生数据更新或用户操作时,界面通过事件通知管理它的Mediator,然后Mediator会根据情况发送通知给系统。先建议一个登录的界面:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Panel xmlns:mx=”http://www.adobe.com/2006/mxml”
    fontSize=”12″
    layout=”vertical”
    horizontalAlign=”center”
    title=”用户登录”
    width=”314″>
 <mx:Script>
  <![CDATA[
   import system.NameSpace;
  ]]>
 </mx:Script>
 <mx:Form width=”100%”
    height=”100%”>
  <mx:FormHeading label=”敬请登录”/>
  <mx:FormItem label=”登录名称”>
   <mx:TextInput id=”loginName”/>
  </mx:FormItem>
  <mx:FormItem label=”登录密码”>
   <mx:TextInput id=”loginPassword”/>
  </mx:FormItem>
  <mx:FormItem>
   <mx:Button label=”确定”
        id=”loginBtn”
        click=”dispatchEvent(new Event(NameSpace.LoginEvent))”/>
  </mx:FormItem>
 </mx:Form>
 <mx:Label id=”labStatus”/>
</mx:Panel>

基于这个界面,定义两个Mediator:一个是LoginMediator,负责管理登录对话框和登录的操作;另一个是ApplicationMediator,用来负责管理登录成功后的界面。先看LoginMediator:

package view
{
 import flash.events.Event;

 import model.vo.LoginVO;

 import mx.managers.PopUpManager;

 import org.puremvc.as3.interfaces.IMediator;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.mediator.Mediator;

 import system.NameSpace;

 public class LoginMediator extends Mediator implements IMediator
 {
  //获取应用实例
  private var loginPanel:LoginForm;
  private var loginApplication:PureLoginMVC;

  public function LoginMediator(app:Object)
  {
   super(NameSpace.LoginMediatorName, app);
   loginApplication=app as PureLoginMVC;
   loginPanel=new LoginForm();
   loginPanel.addEventListener(NameSpace.LoginEvent, onLogin);
   PopUpManager.addPopUp(loginPanel, loginApplication);
   PopUpManager.centerPopUp(loginPanel);
  }

  //监听通知
  override public function listNotificationInterests():Array
  {
   var arr:Array=new Array();
   arr.push(NameSpace.LoginSuccess);
   arr.push(NameSpace.LoginFailed);
   return arr;
  }

  //响应通知
  override public function handleNotification(notification:INotification):void
  {
   switch (notification.getName())
   {
    case NameSpace.LoginSuccess:
     setLoginSuc();
     break;
    case NameSpace.LoginFailed:
     setLoginFailed();
     break;
    default:
     break;
   }
  }

  //登录成功,移除登录窗口
  private function setLoginSuc():void
  {
   PopUpManager.removePopUp(loginPanel);
  }

  //登录失败,提示
  private function setLoginFailed():void
  {
   loginPanel.labStatus.text=”用户名密码有误,请重试”;
   loginPanel.loginName.setFocus();
  }

  private function onLogin(evt:Event):void
  {
   if (loginPanel.loginName.text != “” && loginPanel.loginPassword.text != “”)
   {
    var loginVO:LoginVO=new LoginVO();
    loginVO.username=loginPanel.loginName.text;
    loginVO.password=loginPanel.loginPassword.text;
    sendNotification(NameSpace.ApplicationLogin, loginVO);
   }
   else
   {
    loginPanel.labStatus.text=”请输入用户名和密码”;
   }
  }

 }
}

同样,LoginMediator 的名称来自于 NameSpace.as ,继承Mediator实现IMediator,LoginMediator 注册监听了两个事件:登录成功和失败,并做了对应的响应处理。其中onLogin()方法在收集了登录信息后,发出通知。另外还有一个ApplicationMediator:

package view
{
 import model.vo.LoginVO;

 import mx.controls.Label;

 import org.puremvc.as3.interfaces.IMediator;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.mediator.Mediator;

 import system.NameSpace;

 public class ApplicationMediator extends Mediator implements IMediator
 {
  private var loginApplication:PureLoginMVC;

  //构造器,获取application实例
  public function ApplicationMediator(app:Object)
  {
   super(NameSpace.ApplicationMediatorName, app);
   loginApplication=app as PureLoginMVC;
  }

  //监听通知
  override public function listNotificationInterests():Array
  {
   return [NameSpace.LoginSuccess];
  }

  //响应通知
  override public function handleNotification(notification:INotification):void
  {
   switch (notification.getName())
   {
    case NameSpace.LoginSuccess:
     setLoginSuc(notification.getBody() as LoginVO);
     break;
    default:
     break;
   }
  }

  private function setLoginSuc(loginVO:LoginVO):void
  {
   var label:Label=new Label();
   label.text=”欢迎光临!” + loginVO.username;
   loginApplication.addChild(label);
  }

 }
}

这个mediator只监听了登录成功的通知,并响应更新主应用上的数据。

Controller 和 Command

Controller和Command看起来像一条纽带,联系这Mediator和Proxy.它处理Mediator发送的通知并调用Proxy中的public 方法来处理. Command需要继承SimpleCommand或MocroCommand并实现ICommand.分析系统,需要在Command中注册Proxy和Mediator,以及一个处理Login的。这里的设计思路为:ModelCommand(用于注册Proxy)、ViewCommand(注册Mediator)、ApplicationCommand(用于系统启动时,集成ModelCommand和ViewCommand)、LoginCommand(用于接收登录通知并调用Proxy实现登录)。先看ModelCommand:

package Controller
{
 import model.LoginProxy;

 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 public class ModelCommand extends SimpleCommand implements ICommand
 {
  public function ModelCommand()
  {
   super();
  }

  override public function execute(notification:INotification):void
  {
   facade.registerProxy(new LoginProxy());
  }

 }
}

接着写ViewCommand:

package Controller
{
 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 import view.ApplicationMediator;
 import view.LoginMediator;

 public class ViewCommand extends SimpleCommand implements ICommand
 {
  public function ViewCommand()
  {
   super();
  }

  //注册Mediator
  override public function execute(notification:INotification):void
  {
   var app:PureLoginMVC=notification.getBody() as PureLoginMVC;
   facade.registerMediator(new ApplicationMediator(app));
   facade.registerMediator(new LoginMediator(app));
  }

 }
}

在ApplicationCommand中集成注册上面两个Command:

package Controller
{
 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.patterns.command.MacroCommand;

 public class ApplicationCommand extends MacroCommand implements ICommand
 {
  //构造器,可写可不写
  public function ApplicationCommand()
  {
   super();
  }

  //写法一
  override protected function initializeMacroCommand():void
  {
   addSubCommand(ModelCommand);
   addSubCommand(ViewCommand);
  }

 }
}

处理登录通知的LoginCommand:

package Controller
{
 import model.LoginProxy;
 import model.vo.LoginVO;

 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 import system.NameSpace;

 public class LoginCommand extends SimpleCommand implements ICommand
 {
  public function LoginCommand()
  {
   super();
  }

  override public function execute(notification:INotification):void
  {
   var loginVO:LoginVO=notification.getBody() as LoginVO;
   //var loginProxy:LoginProxy = new LoginProxy();
   //从facade中获取proxy
   var loginProxy:LoginProxy=facade.retrieveProxy(NameSpace.LoginProxyName) as LoginProxy;
   loginProxy.CheckLogin(loginVO);
  }

 }
}

完成了这些之后,就到了 PureMVC 的核心:Facade,通过它,Mediator,Proxy,Command才能很好的结合在一起。这里将它命名为MyFacade,代码如下:

package MyApp

{

import MyApp.Controller.GetUrlListCommand;

import MyApp.Controller.StartUpCommand;

import org.puremvc.as3.interfaces.IFacade;

import org.puremvc.as3.patterns.facade.Facade;

 

public class MyAppFacade extends Facade implements IFacade

{

public static const APP_STARTUP:String = 'app_startup';

public static const APP_STARTUP_OVER:String = 'app_startup_over';

public function MyAppFacade()

{

super();

}

public static function getInstance():MyAppFacade {

if (instance == null) {

instance = new MyAppFacade();

return instance as MyAppFacade;

}

override protected function initializeController():void {

super.initializeController();

//注册一些command

registerCommand(APP_STARTUP, StartUpCommand);

registerCommand(APP_STARTUP_OVER, GetUrlListCommand);

}

public function startup(app:Object):void {

sendNotification(APP_STARTUP, app);

}

}

}

 最后,在主应用中单例调用MyFacade的实例:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application fontSize=”12″
    xmlns:mx=”http://www.adobe.com/2006/mxml”
    creationComplete=”init()”
    layout=”absolute”>
 <mx:Script>
  <![CDATA[
   import system.MyFacade;
   import org.puremvc.as3.patterns.facade.Facade;

   public function init():void
   {
    var myFacade:MyFacade=MyFacade.getInstance();
    myFacade.startup(this);
   }
  ]]>
 </mx:Script>
</mx:Application>

到此为止,一个PureMVC构建的登录例子就完成了,呵呵,希望能达到一看就懂的效果~

源码下载:PureMVCLogin.rar (523)

你可能感兴趣的:(String,function,Flex,command,application,import)