FLEX 扩展Cairngorm框架-减少对Model Locator的依赖

       最近,我公司计划将技术框架由J2EE+ORACLE迁移到FLEX+J2EE+ORACLERIA是大势所趋,用户体验越来越重要。公司在FLEX前端选择了cairngorm微架构,用于处理客户端交互与服务器远程通讯。如何发挥架构优点,避免架构缺点成为一个关键问题。本文的主要目标就是针对cairngorm微架构过于依赖Model Locator的缺点对架构进行调整和扩展,同时还简化了Cairngorm框架的工作流程

一、Cairngorm框架的工作流程:

1.         前端控制器(FrontController)监听用户行为

前端控制品是Cairngorm事件的唯一监听者,但其不并做任何操作,只是集中注册并管理事件(Event)与命今(Command)的映射关系。

2.         命令(Commands)执行所有用户操作

前端控制品(FrontController)监听到事件与命令有匹配时,便告诉命令(Commmands)调用execute()方法处理事件。

3.         服务器端业务逻辑委托给Business Delegate

当命令(Commands)执行时,它只是关心是否获取到数据,而并不关心获取到什么具体数据。因为经常需要从服务器端获取数据,此时命令(Commands)更喜欢把它委托给其它类去操作。所以需要处理服务器端业务逻辑的时候,你都可以委托给命令(Commands)可以调用的Business Delegate类去处理。

4.         Business DelegateService Locator中寻找RPC Services

Business Delegate给命令(Commands)和RPC Services提供一个无缝接口。Business Delegate通过查找和匹配 PRC Services的名称来调用services并返回结果给命令(Commands)。命令(Commands)要从Business Delegate获取返回结果数据必须通过IResponder接口(mx.rpc.IResponder),只有这样Business Delegate才知道命命令(Commands)有onResult()onFault()来处理返回的数据。

5.         把数据存储为Value Objecs

强烈推荐把数据存储为Value Objects

6.         Model Locator保存状态并且让Model通知View

Model Locator是一个保存应用程序全部状态和包含Value Objects的地方。当应用程序状态改变时,Moel Locator 通过Data Binding方式来通知View改变。

Cairngorm框架的工作流程存在如下主要问题:

二、Cairngorm框架的工作流程问题分析与解决办法

       该工作流程在实践中的一个主要问题是Model Locator全局单例类,该设计将应用中的所有数据集中于Model Locator,有很多优点,也导致了众多问题出现,如:

1.         灵活性低:相当于一个新的GOD类,知道应用中所有信息。而复杂应用中的众多数据难以被一个GOD类包含。框架对Model Locator存在严重依赖,未来的变更将变得困难。

2.         问题测试困难:Model Locator对所有Commands公开,当出现数据问题时,难以检查问题原因。

3.         数据校验困难:View通过绑定刷新显示,难以对数据进行检查和校验,从而也不能更友好的进行用户提示。View不能直接得到数据,不方便对数据进行检查和其他处理。

框架扩展方案主要有如下2种:

1.         在命令(Commands)获取返回结果数据,分发数据变更事件。UI对象(View)监控数据变更事件,更新View

a)         原理:本方案直接利用了FLEX的事件处理机制,显得比较直观。

b)        优点:不再依赖Model LocatorView监控解决了数据校验问题。

c)         缺点:增加事件嵌套层次,增加了复杂度。命令(Commands)的重用变得困难,因为一旦重用就存在多个View监听同一事件的问题,出现事件交叉。问题测试困难没有彻底解决。

2.         UI对象(View)作为事件的发起者,将View更新的方法变成Responder,从事件传递给命令(Commands)。命令(Commands)获取返回结果数据后,调用View更新的方法更新View在同一个Application中同时启动多个View实例不会出现数据交叉影响的情况。

a)         原理:Responder,利用了函数式编程。View应该知道当数据变化时如何更新自己。

b)        优点:无数据交叉和事件交叉。不依赖Model Locator。解决了数据校验问题。本方案是变化小、影响小、效果好的解决方案。

二、扩展后的Cairngorm框架

扩展后的cairngorm框架示意图(仅包含扩展部分)

 

 

 

 

 

扩展后的框架图(中间一层为原Cairngorm框架中的部分类)

1.         Event的扩展和调用

a)         事件Event继承自ViewCallbackEvent

b)        View中定义回调方法callbacks

c)         View中根据用户请求分发事件ViewCallbackEvent

2.         Command的扩展

a)         Command继承自ViewCallbackCommand

b)        Command获得事件Event中的callbacks

c)         Command执行Delegate,从服务器获取数据

d)        获取数据后,调用callbacks更新事件对应的View

 

三、示例代码

1.         ViewCallbackEvent实现

       public class ViewCallbackEvent extends CairngormEvent

       {

              private var _callbacks:CallBacks;//Viewcallback异步调用

              public function ViewCallbackEvent(EVENT_ID:String,callbacks:CallBacks)

              {

                     super(EVENT_ID);

                     this._callbacks = callbacks;

              }

              public function get callbacks():CallBacks{

                     return _callbacks;

              }

       }

 

2.         event调用示例

     var callbacks:CallBacks = new CallBacks(resultDate,faultHandler);

     var event:CurrentServerTimeEvent = new CurrentServerTimeEvent(callbacks,"today","yyyy-MM-dd HH:mm:ss");

     event.dispatch();

3.         ViewCallbackCommand  实现

       public class ViewCallbackCommand  implements ICommand, IResponder

       {

              private var callbacks:CallBacks;

              /**

               * 默认的指定函数,需调用

               *

               **/

              public function execute(event:CairngormEvent):void

              {     

                     var e: ViewCallbackEvent = event as ViewCallbackEvent;

                     this.callbacks = e.callbacks;

              }

              /**

               * 默认的成功返回函数,如果没有处理,可以不重载

               *

               **/

              public function result(data:Object):void

              {

                     if(callbacks!=null){

                            callbacks.result(data);

                     }

              }

              /**

               * 默认的返回函数,自动调用外部的返回

               **/

              public function fault(event:Object):void

              {

                     var faultEvt:FaultEvent = event as FaultEvent;

                     //Error Management goes here

                     trace(faultEvt.fault.faultString);

                     if(callbacks!=null){

                            callbacks.fault(event);

                     }

              }

       }

4.         Command示例

       public class CurrentServerTimeCommand extends ViewCallbackCommand 

       {

              override public function execute(event:CairngormEvent):void

              {

                     //此句必须

                     super.execute(event);

                     // cast

                     var e:CurrentServerTimeEvent =event as CurrentServerTimeEvent;

                     var delegate :CoreDelegate = new CoreDelegate( this );

                     delegate.currentServerTime(e.defaults,e.format);                                 

              }

             

              override public function result(data:Object):void

              {

                     //如果要重写,此句必须

                     super.result(data);

                     //此处可以写自己的处理方法,可以使用Model Locator

                     var returnedData:String = data.result as String;

                     ModelLocator.getInstance().currentServerTime = returnedData;

              }

       }

 

如果不熟悉cairngorm框架,请参考:

http://www.adobe.com/devnet/flex/articles/cairngorm_pt1.html官方框架介绍

http://hideto.javaeye.com/blog/109149介绍Cairngorm

http://blog.csdn.net/yangyawen/archive/2009/03/04/3955968.aspx flex cairngorm MVC 介绍

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值