[Flex]浅析Mate flex framework在实际项目中的应用

做项目也有很长时间了,也通过很多的Framework: Cairngorm、PureMVC等等。
但是这次我要说的 Mate  Flex Framework,在网络查找了一下,虽然有一些关于 Mate的中文资料,但是基本上都介于介绍和宣传之类的问题,几乎没有关于 Mate在实际应用中的作用。
那么我就来结合我使用 Mate  Flex Framework的一些心得,介绍一下 Mate在实际项目中的作用。

什么是 Mate Flex  Framework:
Mate是一个基于标签(tag-based)的事件驱动(event-driven)的Flex框架,是由AsFusion创建的。

 

它的特点:

1、与Cairngorm类似也是基于event handler,但是也不同与Cairngorm,因为它没有备受争议的frontControler和频繁的使用单例模式。

2、与PureMVC就更加的不同了。Mate是完全的基于Flex的Framework,而不像PureMVC那样是一个独立的框架。

3、它是基于标签形式的,因此它的语法势必比较容易通读,但是这也限制了它的作用,因为Mate只能应用在MXML里面,即由Flex开发的project,而无法适用于完全由AS写的project。

     这是一个比较典型的Mate语法结构:

     <EventHandlers type="{QuoteEvent.GET}" debug="true">

   <RemoteObjectInvoker destination="ColdFusion"
      source="stockQuoteExample.QuoteService"
      method="getQuote"
      arguments="{event.symbol}"
      debug="true">

      
      
<resultHandlers>
         
<MethodInvoker generator="{QuoteManager}"
            method="storeQuote" arguments="{resultObject}"/>

      
</resultHandlers>

   </RemoteObjectInvoker> 
  </EventHandlers>

 

Mate的驱动者:
http://mate.asfusion.com/
大量的sample:
http://mate.asfusion.com/page/examples
 
Mate显著的三个特点:
EventMap(事件地图)、Injectors(依赖注入机制)、Extensions(插件、扩充)机制。
 
Mate flex framework的优势:
1、它可以应用在你已经开发了一半的 Flex Project里面(只需要应用它的EventMap方式即可)同时也不会破坏掉原有的结构。
    而 Cairngorm、PureMVC如果要应用在已经开发了一半的project的话,首先它们是很难应用的,就算是强行应用的话,那么无疑会破坏掉原有project的结构。
2、由于是基于标签方式,因此可读性比较强,同时学习难度也远远的小于Cairngorm、PureMVC。一个Flex的初学者在很短时间(下载运行调试一下Mate sample例子就应该可以上手了)内就肯定会掌握Mate了。
3、Mate由于只能在Flex里面使用,因此它比较适用于中小型团队的Flex Project开发。
4、它独有的extensions机制,可以将具体的一些功能的抽出和再应用。
 
那么Mate的缺点:
1、由于是基于标签形式,因此只能在Flex里面使用,因此限制了它的应用范围。
2、我个人认为不太适用于大型Flex Framework Project。因为它的优势EventMap在大型项目的情况下会变成它的缺点

==================================================================================

本篇文章是结合实际的flex project来分别的说一下这个三个特性:(本篇文章只介绍EventMap)
一、EventMap(事件地图)
我不知道官方的中文叫法是什么?但是我还是比较中意这种直译的方式:事件地图。
举例子说明:
我有三个MXML文件:A.mxml、B.mxml、C.mxml。而它们之间的关系是:A包含B,B包含C。
现在我想在C中触发一个事件,而最终会反映到A中,因此我做了如下的设定。
我定义如下一个customer event:MyEvent(请看下面的片段代码)
    
    
    
    
  1. public class MyEvent extends Event {
  2.  
  3. public static const CLICK_ME : String = "clickMe";
  4.  
  5. public function SupporterListEvent ( type : String, bubbles : Boolean= false, cancelable : Boolean= false ) {
  6. super ( type, bubbles, cancelable );
  7. }
 

其中A.mxml里面监听了此方法。

    
    
    
    
  1. this. addEventListener ( MyEvent.CLICK_ME , myEventHandler );

那么我在C.mxml里面触发了这个event:

    
    
    
    
  1. dispatchEvent ( new MyEvent ( MyEvent.CLICK_ME ) );

那么通常的情况是有A与C之间没有任何关系,因此C虽然触发了这个event,但是无法正常的传递到A中(我只说通常的情况)
因此,我们需要在B.mxml里面也写上如下的内容:

   
   
   
   
  1. //监听C传递过来的event
  2. //注意这是在B中监听的
  3. this. addEventListener ( MyEvent.CLICK_ME , myEventHandler );

 因此当C触发MyEvent.CLICK_ME后,会被B监听,当B监听到C的事件后,再次使用

    
    
    
    
  1. //注意:这是在B中触发的
  2. dispatchEvent ( new MyEvent ( MyEvent.CLICK_ME ) );

最终由于A中已经监听了MyEvent.CLICK_ME,因此就可以收到C中触发的事件了(通过B进行了一次传递)。
虽然这样也能完成最初的目的:C → A,那么我们需要在B里面写上一些代码,这样做的缺陷是增加了coding时间,同时也降低了source的可读性。
同时也增加了A、B、C的耦合性,因此上述方案不是一个较好的resolution。

而Mate Flex Framework给我们提供的解决方案:使用EventMap

那么我们如何利用EventMap呢?
1、首先需要引入mate swc。地址:http://mate.asfusion.com/page/downloads
2、定义一个folder:maps
然后在其中定义一个EventMap:MyEventMap.mxml(片段代码如下)

    
    
    
    
  1. <EventMap xmlns :mx= "http://www.adobe.com/2006/mxml"
  2. xmlns= "http://mate.asfusion.com/" >
  3.  
  4. <mx :Script >
  5. <! [CDATA [
  6. import com.wonlen. test.A;
  7. ] ] >
  8. </mx :Script >
  9.  
  10. <EventHandlers type= "{ MyEvent.CLICK_ME }" >
  11. <MethodInvoker generator= "{ A }" method= "myEventHandler" />
  12. </EventHandlers >
  13.  
  14. </EventMap >

请注意:
1、A:就是我我们要被触发的目标位置。
2、myEventHandler:我们之前定义的一个event handler

    
    
    
    
  1. this. addEventListener ( MyEvent.CLICK_ME , myEventHandler );

那么我来解释一下上诉的代码:
首先在MyEventMap里面定义如下的结构:

    
    
    
    
  1. <EventMap xmlns :mx= "http://www.adobe.com/2006/mxml"
  2. xmlns= "http://mate.asfusion.com/"
  3. xmlns :extensions= "com.asfusion.weather.mate.extensions.*" >
  4. </EventMap >

然后就是我们这次的重头戏了:

    
    
    
    
  1. <EventHandlers type= "{ MyEvent.CLICK_ME }" >
  2. <MethodInvoker generator= "{ A }" method= "myEventHandler" />
  3. </EventHandlers >

上面的结构我用中文说一下:
1、当在C中触发了dispatchEvent( new MyEvent( MyEvent.CLICK_ME ));
2、会通过EventMap”寻找到“到类型为 MyEvent.CLICK_ME的eventHandler(即上图定义的结构)
3、只后会寻找到这段结构:
它的结构是:定义了接受event handler之后的对象A,然后调用的methode:myEventHandler

最后一个步骤:
我们在这个project的主文件下面(即有

    
    
    
    
  1. < maps :MyEventMap />

然后我们可以去掉在A中的监听:

    
    
    
    
  1. this. addEventListener ( MyEvent.CLICK_ME , myEventHandler );

通过以上以上的代码,那么最终的过程:
当C触发MyEvent.CLICK_ME后,会通过EevntMap找到type为MyEvent.CLICK_ME的结构,触发完毕后会调用的目标对象A中的myEventHandler函数。

也就说通过EventMap,我们可以让MyEvent.CLICK_ME传递到任意地方:MXML文件里面、AS文件里面都是完全可行的。

EventMap的特点:
它会帮助你的project 和 Flex来管理这些乱七八的事件,也就是只要是在同一个project里面,我可以通过EventMap将任何两个mxml之间通过事件传导的方式联系起来。
EventMap将事件(行为)与最终事件处理(动作)联系了起来。


 


由于它将行为与动作绑定起来了,因此也带来了两个缺点:
1、当一个project里面有100个行为与动作的话,那么我们要在MyEventMap写100段如上的结构,这就变成了一种负担。理所当然的解决方法:我们可以把这些EventMap分开。
例如:ChatEventMap(负责聊天的EventMap)、DrawEventMap(负责绘画的EventMap)等等。
2、由于它利用了Event type来对Event进行区分,因此我们每一个行为与动作都要设定一个唯一的Event type。
如果有100个行为与动作的话,需要设定100个event name,这样的方式的确比较恐怖一些。

以上就是 Mate Flex Framework的EventMap,下次给大家介绍 Mate的Injectors(依赖注入机制),通过这种方式可以真正实现mvc的分离,而不需要使用备受Cairngorm、PureMVC用户痛苦的单例模式。


=====================================================================
经过上两篇文章的洗礼,希望大家可以对 Mate  Flex framework有了一些初步的了解。那么今天我们进行 Mate  Flex Framework的重头戏:Injectors(依赖注入机制)、
二、Injectors(依赖注入机制)

那么什么时候Injectors(依赖注入机制)呢?
具体可以看这里,人家已经描述的很清楚了,我就没有必要再重复一遍了:)
http://www.adobe.com/devnet/flex/articles/dependency_injection.html

如何使用 Mate  Flex Framework来完成Injectors(依赖注入机制):
好吧,我们接着上篇文章的一个例子来说明一下,当C.mxml触发了dispatchEvent( new MyEvent( MyEvent.CLICK_ME ));后,会很容易的被EventMap传递到任何我想传递的地方。
代码如下:
    
    
    
    
  1. <EventMap xmlns :mx= "http://www.adobe.com/2006/mxml"
  2. xmlns= "http://mate.asfusion.com/" >
  3.  
  4. <mx :Script >
  5. <! [CDATA [
  6. import com.wonlen. test.A;
  7. ] ] >
  8. </mx :Script >
  9.  
  10. <EventHandlers type= "{ MyEvent.CLICK_ME }" >
  11. <MethodInvoker generator= "{ A }" method= "myEventHandler" />
  12. </EventHandlers >
  13.  
  14. </EventMap >

而这个时候,我增加了一个需求:
我想让C不仅可以传递消息还想让A得到C传递过来的消息后,显示到UI上面。
例如:在A上面显示如下的内容:C跟你打了声招呼。我是A,我得到了你传递过来的消息。

为了降低A与C的耦合性,因此A是不知道C的存在的,而C也只会把自己的消息传递出去,而不会理会到底是A接受到,还是D接收到。
上面的一个需求其是就将mvc的特征体现出来到了,即显示层(v)、控制层(c)、逻辑层(m)独立分开。

okay,由于需要传递参数,所以需要改写MyEvent.as,增加一个public variable :name,代码如下:

    
    
    
    
  1. public class MyEvent extends Event {
  2.  
  3. public static const CLICK_ME : String = "clickMe";
  4.  
  5. public var name : String;
  6.  
  7. public function SupporterListEvent ( type : String, bubbles : Boolean= false, cancelable : Boolean= false ) {
  8. super ( type, bubbles, cancelable );
  9. }

注意:真正在实际应该用,不用直接采用public的方式,而是应该采用setter、getter的方式,这样可以更好的控制闭包。
okay,我们已经增加了一个变量:name,它的作用是用来保存触发者的名字。因此C.mxml的代码也需要稍微的修改一下,主要对name进行赋值。

    
    
    
    
  1. var myEvent : MyEvent = new MyEvent ( MyEvent.CLICK_ME );
  2. myEvent. name = "C";
  3. dispatchEvent ( myEvent );

上面的代码比较简单,不做过多介绍。
okay,既然现在已经把名字保存起来了,那么我们需要一个逻辑对这个传入的参数进行一些处理。我们增加一个叫做business的文件(注意这里的名称与Cairngorm、PureMVC是相似而的)
然后在business文件夹下面增加一个AS文件:MyController.as,然后里面的内容如下:

    
    
    
    
  1. package com.wonlen. test.business
  2. {
  3. public class MyController {
  4.  
  5. [Bindable ]
  6. public var talk : String;
  7.  
  8. [Bindable ]
  9. public var type : String;
  10.  
  11. [Bindable ]
  12. public var name : String;
  13.  
  14.  
  15. // ----------------------------------------------------------
  16. public function settingTalks ( ) : void {
  17.  
  18. if ( type == "clickMe" ) {
  19. talk = name + "跟你打了声招呼。";
  20. }
  21. else {
  22. talk = name + "离开了。";
  23. }
  24. }
  25. }
  26. }

上面的代码,也是比较简单的,增加了三个属性,type 和 name。它们的意义上分别是:
1、type:类型。
2、name:名字。
3、talk:保存经过设定后的字符串。

经过上面的修改,我们完成了事件携带值的修改和定义了一个controller性质的AS:MyController
接下来在A.mxml里面增加一些内容,例如如下的source:

    
    
    
    
  1. <?xml version= "1.0" encoding= "utf-8" ?>
  2. <mx :Panel xmlns :mx= "http://www.adobe.com/2006/mxml" title= "A Panel" >
  3.  
  4. <mx :Script >
  5. <! [CDATA [
  6. [Bindable ]
  7. public var othertalks : String;
  8. ] ] >
  9. </mx :Script >
  10.  
  11. <mx :Label text= "{ othertalks + '我是A,我得到了你传递过来的消息' }" />
  12.  
  13. </mx :Panel >

我定义了一个变量:othertalks,它的作用是用于显示接收的内容。
那么MyEventMap应该如下修改呢?请看下面的代码:

    
    
    
    
  1. <EventMap xmlns :mx= "http://www.adobe.com/2006/mxml"
  2. xmlns= "http://mate.asfusion.com/" >
  3.  
  4. <mx :Script >
  5. <! [CDATA [
  6. import com.wonlen. test.A;
  7. ] ] >
  8. </mx :Script >
  9.  
  10. <EventHandlers type= "{ MyEvent.CLICK_ME }" >
  11. <MethodInvoker generator= "{ MyController }" method= "settingTalks" >
  12. <Properties type= "{ MyEvent.CLICK_ME }" name= "{ 'C' }" />
  13. </MethodInvoker >
  14. </EventHandlers >
  15.  
  16. <Injectors target= "{ A }" >
  17. <PropertyInjector targetKey= "othertalks" source= "{ MyController }" sourceKey= "talk" />
  18. </Injectors >
  19.  
  20. </EventMap >

这次MyEventMap改动就比较大了,不过都是比较好理解的,我现在给大家解释一下:

    
    
    
    
  1. <MethodInvoker generator= "{ MyController }" method= "settingTalks" >
  2. <Properties type= "{ MyEvent.CLICK_ME }" name= "{ 'C' }" />
  3. </MethodInvoker >

它定义了一个段,这个段上次我应该已经讲过了,只不过上次的generator = A,而这次是:MyController而已。
让我们在回顾一下,MyController的内容:
1、一个method:settingTalks
2、三个参数:type、name(传入的两个properties)、talk(这是用于保存字符串的变量)

既然需要传入两个参数,所以我们就定义了一个属性段,它在Mate里面是专门负责用于对XXX的属性进行赋值的工作。
那么整个这个段的作用是什么?
当触发MyEvent.CLICK_ME后,同时传入了两个参数:type 和 name。然后会调用MyController里面的method:settingTalks。
当这一切都完成后,Mate就会调用里面的内容,让我们看一下的内容

    
    
    
    
  1. <Injectors target= "{ A }" >
  2. </Injectors >

首先注入的目标对象是A,接下来的代码;

    
    
    
    
  1. <PropertyInjector targetKey= "othertalks" source= "{ MyController }" sourceKey= "talk" />
我们分析一下上面的代码,定义了要被注入的属性,也就是A中那个变量被进行了注入操作。
targetKey="othertalks",说明了被注入的属性是A.mxml里面的othertalks。
source="{ MyController }" sourceKey="talk":说明了使用的MyController里面的属性talk作为注入属性,即将MyController.talk 赋值给A.othertalks。

okay,这就是MyEventMap增加的内容。那么截止到目前所有增加的内容都已经说明过了。

我现在重述一下上面的内容:
当在C中触发了MyEvent.CLICK_ME后,会在EventMap里面调用MyController,并且传入了type 和 name,然后通过settingTalks,最后得到了字符串talk。
然后将MyController.talk通过注入方式赋值给A.othertalks,最终显示在A上面:C跟你打了声招呼。我是A,我得到了你传递过来的消息。

其实经过以上的coding,就形成了一些简单的mvc方式。C只负责触发MyEvent.CLICK_ME,而它无须理会到底是给谁的。
同时A也只负责接收MyEvent.CLICK_ME的消息,而无须理会具体的逻辑是什么,只是单纯的显示得到的结果。
MyController封装了主要的业务逻辑,如果一但有需求变更的话,那么我们只负责修改MyController里面的逻辑即可。
由于这个例子比较小,因此我只使用了变量来代替vo。



原文地址:http://www.k-zone.cn/zblog/post/flex-mate-framework-1.html

你可能感兴趣的:(mvc,function,String,Flex,import,generator)