Flex 开发架构(二): 中央管理-Flex Central Managerment
2008-10-13 23:42 宝宝合凤凰 阅读(502) 评论(0) 收藏 举报Flex 开发架构(二): 中央管理-Flex Central Managerment
http://houwei.javaeye.com/blog/219666
Flex Chaos-All-in-one这一节中所提到的,在大型项目中,将所有的代码放在一起并非明智之举,确切的讲:正确的方法是将商业逻辑层与UI层分离开来。
中央管理的理念是使用一个远程对象管理器来控制Flex与后端的通讯。其构建体系如下图所示
图中每一个UI组件都将调用一个服务(Service),服务类将调用中央管理器(Central Manager),中央管理器类将调用服务器端的解决方案。而图中全局对象管理器(Global Object Manager)将用来在UI之间传递数据。
现在来看看简单密友列表应用的实现。
首先是LoginView.xml
- <?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Panel xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” width=”300″ height=”200″ horizontalAlign=”center” verticalAlign=”middle” title=”Flex Central Manager Login”>
- <mx:Script>
- <![CDATA[
- import com.ny.flex.centralManagement.service.LoginService;
- import mx.validators.Validator;
- import mx.containers.ViewStack;
- import mx.rpc.events.ResultEvent;
- private function login():void{
- if(Validator.validateAll(validators).length == 0){
- LoginService.getInstance().login(username.text,password.text);
- }
- }
- ]]>
- </mx:Script>
- <!– Validators–>
- <mx:Array id=”validators”>
- <mx:StringValidator id=”userNameValidator” source=”{username}” property=”text” required=”true”/>
- <mx:StringValidator id=”passwordValidator” source=”{password}” property=”text” required=”true” />
- </mx:Array>
- <mx:Form id=”loginForm” x=”0″ y=”0″>
- <mx:FormItem label=”Username:” >
- <mx:TextInput id=”username” />
- </mx:FormItem>
- <mx:FormItem label=”Password:” >
- <mx:TextInput id=”password” displayAsPassword=”true” />
- </mx:FormItem>
- <mx:FormItem direction=”horizontal” verticalGap=”15″ paddingTop=”5″ width=”170″>
- <mx:Button id=”loginBtn” label=”Login” click=”login()”/>
- </mx:FormItem>
- </mx:Form>
- </mx:Panel>
其功能的核心是:
LoginService.getInstance().login(username.text,password.text);
它的作用是有效的分离了商务逻辑层和视图组件。在此服务类程序不需支持任何状态,因此我们保持其单件模式(singleton)。
LoginService类文件如下:
- import com.ny.flex.centralManagement.event.DataManagerResultEvent;
- import com.ny.flex.centralManagement.manager.GlobalObjectManager;
- import com.ny.flex.centralManagement.manager.RemoteObjectManager;
- public class LoginService
- {
- public var roManager:RemoteObjectManager = null;
- public var gom:GlobalObjectManager = GlobalObjectManager.getInstance();
- private static var _instance:LoginService =null;
- public static function getInstance():LoginService{
- if(_instance == null){
- _instance = new LoginService(new PrivateClass)
- }
- return _instance;
- }
- public function LoginService(privateclass:PrivateClass)
- {
- if(LoginService._instance == null){
- LoginService._instance = this;
- }
- }
- public function login(userName:String,password:String):void{
- roManager = RemoteObjectManager.getRemoteObjectManager(”flexmvcRO”);
- roManager.addEventListener(”getLoginUser”,loginHandler);
- var params:Array = new Array(userName,password);
- roManager.makeRemoteCall(”getLoginUserName”,”getLoginUser”,params);
- }
- private function loginHandler(event:DataManagerResultEvent):void {
- var userName:String = event.result as String;
- if(userName){
- gom.loginUserName = userName;
- gom.viewStackSelectedIndex=1;
- }
- }
- }
代码中有两个特别的对象:
RemoteObjectManager
GlobalObjectManager
RemoteObjectManager是一个单件的类,用来实现中央管理所有的远程对象通讯。原始的代码来自于Jeff Tapper的博客:
Creating a Remote Object DataManager in ActionScript 3.0 for Flex 2.0
RemoteObjectManager.as:
- package com.ny.flex.centralManagement.manager
- {
- import com.ny.flex.centralManagement.event.DataManagerResultEvent;
- import flash.events.EventDispatcher;
- import mx.core.Application;
- import mx.resources.ResourceManager;
- import mx.rpc.AbstractOperation;
- import mx.rpc.AsyncToken;
- import mx.rpc.events.FaultEvent;
- import mx.rpc.events.ResultEvent;
- import mx.rpc.remoting.mxml.RemoteObject;
- public class RemoteObjectManager extends EventDispatcher {
- public var ro:RemoteObject;
- private var eventName:String;
- private static var instanceMap:Object = new Object();
- public function RemoteObjectManager(pri:PrivateClass,dest:String){
- this.ro = new RemoteObject();
- ro.destination = dest;
- }
- public static function getRemoteObjectManager(dest:String):RemoteObjectManager{
- if(RemoteObjectManager.instanceMap[dest] == null){
- RemoteObjectManager.instanceMap[dest] = new RemoteObjectManager(new PrivateClass(),dest);
- }
- var dm:RemoteObjectManager= RemoteObjectManager.instanceMap[dest];
- return dm;
- }
- public function makeRemoteCall(methodName:String,eventName:String,args:Array=null):void{
- this.eventName = eventName;
- var op:mx.rpc.AbstractOperation = ro[methodName];
- ro.addEventListener("result", doResults);
- ro.addEventListener("fault", doFault);
- var token:AsyncToken = null;
- if(args && args.length >0){
- token = op.send.apply(null,args);
- }
- else {
- token = op.send();
- }
- token.eventName = eventName;
- }
- private function doResults(event:ResultEvent):void{
- var e:DataManagerResultEvent = new DataManagerResultEvent(event.token.eventName, event.result);
- this.dispatchEvent(e);
- }
- private function doFault(fault:FaultEvent):void{
- this.dispatchEvent(fault);
- }
- public override function toString():String{
- return "RemoteObjectDataManager";
- }
- }
- }
- /** PrivateClass is used to make DataManager constructor private */
- class PrivateClass{
- public function PrivateClass() {}
- }
“GlobalObjectManager”用来在UI之间传递信息,例如,我们使用ViewStack的selectedIndex来决定显示ViewStack中的哪一个视图,则使用全局对象viewStackSelectedIndex ,其代码如下面的黑体部分:
- <?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml“ xmlns:views=”com.ny.flex.centralManagement.views.*” layout=”absolute” width=”100%” height=”100%”>
- <mx:Script>
- <![CDATA[
- import mx.binding.utils.BindingUtils;
- import com.ny.flex.centralManagement.manager.GlobalObjectManager;
- [Bindable]
- public var gom:GlobalObjectManager=GlobalObjectManager.getInstance();
- ]]>
- </mx:Script>
- <mx:HBox horizontalAlign=”center” verticalAlign=”top” width=”100%” height=”100%” y=”0″ x=”0″>
- <mx:ViewStack id=”viewStack” resizeToContent=”true” selectedIndex=”{gom.viewStackSelectedIndex}” >
- <views:LoginView />
- <views:BuddyListView/>
- </mx:ViewStack>
- </mx:HBox>
- </mx:Application>
再回头看看在
LoginService 代码中的loginHandler方法,在此viewStackSelectedIndex 全局对象被更新。LoginService
代码中的loginHandler方法,在此viewStackSelectedIndex 全局对象被更新。
- private function loginHandler(event:DataManagerResultEvent):void {
- var userName:String = event.result as String;
- if(userName){
- gom.loginUserName = userName;
- gom.viewStackSelectedIndex=1;
- }
- }
[Bindable]元标签使得其值的改变立刻生效。
BuddyList.mxml代码:
- <?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Panel xmlns:mx=”http://www.adobe.com/2006/mxml” title=”Buddy List of {gom.loginUserName}” creationComplete=”init()” width=”500″ height=”320″>
- <mx:Script>
- <![CDATA[
- import com.ny.flex.centralManagement.service.BuddyService;
- import com.ny.flex.centralManagement.manager.GlobalObjectManager;
- import mx.collections.ArrayCollection;
- import mx.rpc.events.ResultEvent;
- [Bindable]
- public var gom:GlobalObjectManager = GlobalObjectManager.getInstance();
- private function init():void{
- BuddyService.getInstance().getBuddyList();
- }
- ]]>
- </mx:Script>
- <mx:DataGrid id=”buddyList” dataProvider=”{gom.mybuddyList}” borderStyle=”none” width=”100%” height=”100%” >
- <mx:columns>
- <mx:DataGridColumn dataField=”firstName” headerText=”First Name”/>
- <mx:DataGridColumn dataField=”lastName” headerText=”Last Name”/>
- </mx:columns>
- </mx:DataGrid>
- </mx:Panel>
BuddyService是另一个服务类代码用来和远程对象通讯。
这是最符合本人喜好的Flex程序的框架结构。它的优点是非常的清晰,没有累赘的发送和监听事件的工作,并且代码非常容易维护。遗憾的是,在此还没有获得足够的理论支持这一框架理论。
再来看看MVC框架的代表:MVC-Cairngorm。
浙公网安备 33010602011771号