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

来源:互联网 发布:云天明和艾aa 知乎 编辑:程序博客网 时间:2024/05/16 09:36
 最近,我公司计划将技术框架由J2EE+ORACLE迁移到FLEX+J2EE+ORACLE,RIA是大势所趋,用户体验越来越重要。公司在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 Delegate在Service 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 Locator。View监控解决了数据校验问题。

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

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

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

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

二、扩展后的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;//View的callback异步调用

              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 介绍

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wolf_linn/archive/2009/07/24/4373180.aspx

原创粉丝点击