Flex MVC框架PureMVC使用

1.概述

PureMVC实现的经典MVC元设计模式中,这三部分由三个单例模式类管理,分别是ModelViewController。三者合称为核心层或核心角色。各层之间能以一种松耦合的方式通信,并且与平台无关。

1.Model保存对Proxy对象的引用,Proxy负责操作数据模型;

2.View保存对Mediator对象的引用 。由Mediator对象来操作具体的视图组件,包括:添加事件监听器 ,发送或接收Notification ,直接改变视图组件的状态;

3.Controller保存所有Command的映射。Command类是无状态的,只在需要时才被创建。

4.Facade,单例模式,它负责初始化核心层(ModelViewController),还提供对已注册的类的管理。

使用pureMVC,我们只需要实现Proxy、Mediator和Command,还有一个Facade

2.实现Facade

package fad
{
	import controller.*;
	
	import org.puremvc.as3.interfaces.IFacade;
	import org.puremvc.as3.patterns.facade.Facade;
	
	/**
	 * 继承Facade
	 **/
	public class ApplicationFacade extends  Facade implements IFacade
	{
		//Notification name constants
		public static const STARTUP:String		="startup";
		public static const LOGIN:String		="login";		
		public static const CANCEL:String		="cancel";		
		public static const LOGINRESULT:String	="loginReslut";
		public static const SHOW:String		= "show";
		public static const SHOWLOGIN:String 		= "showLogin";
		
		/**
		 * 单例实现
		 **/		
		public static function getInstance():ApplicationFacade{
			if(instance==null)
				instance = new ApplicationFacade;
			
			return instance as ApplicationFacade;
		}
		
		/**
		 * 自己初始化,注册了一些命令
		 **/
		override protected function initializeController():void{
			super.initializeController();
			registerCommand(STARTUP,StartupCommand);
			registerCommand(LOGIN,LoginCommand);
			registerCommand(SHOW,ShowLoginCommand);
		}
		
		/**
		 *  启动函数,发送STARTUP通知,框架会新建StartupCommand命令,并执行
		 **/
		public function startup(app:Object):void{
			sendNotification(STARTUP,app);
		}
	}
}

3.command

Facade中注册了一些命令,需要实现

StartupCommand.as

package controller
{

	import compents.m2login;
	
	import model.LoginProxy;
	
	import org.puremvc.as3.interfaces.ICommand;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	
	import view.LoginMediator;

	public class StartupCommand extends SimpleCommand implements ICommand
	{

		override public function execute(notif:INotification):void
		{
			// 初始化LoginPanel对应的Mediator
			facade.registerProxy(new LoginProxy());
			var app:Hello=notif.getBody()as Hello;//Hello是主界面的名字
			facade.registerMediator(new LoginMediator(app));
		}
	}
}
LoginComand

package controller
{
	import model.LoginProxy;
	import model.vo.LoginUser;
	
	import org.puremvc.as3.interfaces.ICommand;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.command.SimpleCommand;
	
	import view.LoginMediator;

	public class LoginCommand extends SimpleCommand implements ICommand
	{

		override public function execute(notif:INotification):void
		{
			var loginProxy:LoginProxy = facade.retrieveProxy(LoginProxy.NAME) as LoginProxy;
			loginProxy.login(notif.getBody()as LoginUser);
		}

	}
}


StartupCommand继承了框架提供的SimpleCommand,程序启动时调用它注册 LoginProxy和LoginMediator。

Command对象是无状态的;

只有在需要的时候(Controller收到相应的Notification)才会被创建,并且在被执行(调用execute方法)之后就会被删除.

Command要实现ICommand接口。在PureMVC中有两个类实现了ICommand接口:SimpleCommandMacroCommand

SimpleCommand只有一个execute方法,execute方法接受一个Inotification实例做为参数。实际应用中,你只需要重写这个方法就行了。

MacroCommand在构造方法调用自身的initializeMacroCommand方法。实际应用中,你需重写这个方法,调用addSubCommand添加子Command。你可以任意组合SimpleCommandMacroCommand成为一个新的Command


4.Midiator

LoginMediator.as

package view
{
	import fad.ApplicationFacade;
	
	import flash.events.Event;
	
	import model.LoginProxy;
	
	import mx.controls.Alert;
	
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	import view.components.LoginPanel;
	
	public class LoginMediator  extends Mediator implements IMediator {
		public static const NAME:String = "LoginMediator";
		
		public function LoginMediator(viewComponent:Object)
		{
			super(NAME,viewComponent);
			//绑定界面事件处理函数
			hello.addEventListener(LoginPanel.LOGIN,onLogin);
			hello.addEventListener(LoginPanel.CANCEL,onCancel);
			hello.addEventListener(ApplicationFacade.SHOW,onShow);
		}
		
		public function get hello():Hello{
			return viewComponent as Hello;
		}
		
		private function onLogin(event:Event):void{
			sendNotification(ApplicationFacade.LOGIN,hello.loginPanel.loginUser);
		}

		private function onCancel(event:Event):void{
			sendNotification(ApplicationFacade.CANCEL);
		}
		
		private function onShow(event:Event):void{
			this.sendNotification(ApplicationFacade.SHOW);
		}
		
		/**
		 * 以数据形式返回这些Notification 名称,表示这个miediator 响应这些名称的Notification,
		 * 
		 **/
		override public function listNotificationInterests():Array{
			return[ApplicationFacade.LOGINRESULT,ApplicationFacade.CANCEL,ApplicationFacade.SHOWLOGIN];
		}
		
		/**
		 * Notification的响应函数
		 * */
		
		override public function handleNotification(notfi:INotification):void{
			switch(notfi.getName()){
				case ApplicationFacade.LOGINRESULT:
					var result:Boolean = new Boolean(notfi.getBody());
					Alert.show(result?"登录成功":"登录失败");
					break;
				case ApplicationFacade.CANCEL:
					Alert.show("取消登录");
					this.hello.loginPanel.visible = false;
					//facade.removeProxy(LoginProxy.NAME);
					
					break;
				case ApplicationFacade.SHOWLOGIN:
					this.hello.loginPanel.visible = true;
					break;
					
		
			}
		}
	}
}

Mediator保存了一个或多个View Component的引用,通过View Component自身提供的API管理它们.Mediator的主要职责是处理View Component派发的事件和系统其他部分发出来的Notification(通知)。因为Mediator也会经常和Proxy交互,所以经常在Mediator的构造方法中取得Proxy实例的引用并保存在Mediator的属性中,这样避免频繁的获取Proxy实例。
通常一个Mediator只对应一个View Component,但却可能需要管理多个UI控件,例子中管理的是整个页面的视图

1.响应Notification,检查或修改View Component的属性(或调用提供的方法)。
2.响应Notification,检查或修改Proxy对象公布的属性(或调用提供的方法)。
4.发送一个或多个Notification,通知别的Mediatora或Command作出响应(甚至有可能发送给自身)。


5.proxy

LoginProxy

package model
{
	import model.vo.LoginUser;
	
	import mx.controls.Alert;
	
	import org.puremvc.as3.interfaces.IProxy;
	import org.puremvc.as3.patterns.proxy.Proxy;
	import fad.ApplicationFacade;

	public class LoginProxy extends Proxy implements IProxy
	{
		public static const  NAME:String="LOGIN_PROXY";
		
		public function LoginProxy(){
			super(NAME,new Object);
		}
		
		/**
		 * 公共方法,在Command中调用
		 * 
		 **/
		public function login(loginUser:LoginUser):void{

			var result:Boolean = false;
			if(loginUser.loginName=="user" && loginUser.loginPwd=="123456"){
				result =true;
			}
												
			sendNotification(ApplicationFacade.LOGINRESULT,result);//通知mediator
		}
		
		
		/**
		 * 公共方法,在Command中调用
		 * 
		 **/
		
		public function show():void{
			sendNotification(ApplicationFacade.SHOWLOGIN);//通知mediator
}}}

 

LoginUser 是一个自定义的数据类。

Proxy是有状态的,当状态发生变化时发Mediator,将数据的变化反映到视图。Proxy可能会提供访问Data Object部分属性或方法的API,也可能直接提供Data Object的引用。如果提供了更新Data Object的方法,那么在数据被修改时可能会发送一个Notifidation通知系统的其它部分。Proxy不监听Notification,也永远不会被通知,因为Proxy并不关心View的状态。但是,Proxy提供方法和属性让其它角色更新数据。View本质上是显示Model的数据并让用户能与之交互,我们期望一种单向依赖,即View依赖于Model,而Model却不依赖于View。View必须知道Model的数据是什么,但Model却并不需要知道View的任何内容。

View 有个主界面Hello.mxml和一个LoginPanel.mxml

Hello.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns: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:compents="view.components.*" 
			   creationComplete="appFacade.startup(this);"
			  click="onclick();" >
	
	<fx:Metadata>
		[Event('Login')]
		[Event('Cancel')]
		[Event('Show')]
	</fx:Metadata>
	<fx:Script>
		<![CDATA[
			import fad.ApplicationFacade;
			 
			private var appFacade:ApplicationFacade= ApplicationFacade.getInstance();
			
			public function onclick():void{
				dispatchEvent(new Event(ApplicationFacade.SHOW));
			}
			
		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
	</fx:Declarations>
	
	<compents:LoginPanel x="595" y="116" id="loginPanel">
	</compents:LoginPanel>
	
	
</s:Application>

LoginPanel.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" 
		  xmlns:s="library://ns.adobe.com/flex/spark"
	width="344" height="196" layout="absolute"
	creationComplete="initApp()" title="Login">
	
	<mx:Metadata>
		[Event('Login')]
		[Event('cancel')]
	</mx:Metadata>
	
	<mx:Script>
		<![CDATA[
			import model.vo.LoginUser;
			
			[Bindable]
			public var loginUser:LoginUser;
			
			public static const LOGIN:String = "Login";
			public static const CANCEL:String = "Cancel";
			
			// send the named event
			private function sendEvent(event:Event, eventName:String ):void
			{
				loginUser = new LoginUser(userName.text,pwd.text);
				var hello:Hello = this.parent as Hello;
				dispatchEvent( new Event( eventName, true ) );
				event.stopPropagation();
			}

			private function initApp() : void {
				userName.text="user";				
				pwd.text="123456";
			}   
		]]>
	</mx:Script>
	
	<s:Label x="56" y="43" text="UserName"/> 
	<s:TextInput id="userName" x="120" y="41" />
	
	<s:Label x="56" y="69" text="Passward"/> 
	<s:TextInput id ="pwd" x="120" y="67" displayAsPassword="true"/>	
	
	<s:Button x="100" y="115" name="login" label="Login" click="sendEvent(event,LOGIN)"/>
	<s:Button x="187" y="115" label="Cancel" click="sendEvent(event,CANCEL)"/>
		
</mx:Panel>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值