本文来自:http://www.cnblogs.com/zhainanJohnny/archive/2010/11/28/1890356.html
上一篇介绍了一下Cairngorm的基本组成,下面我给大家展示一个简单的例子。
我们按一个完整的Cairngorm流程来介绍这个例子。这个例子很简单,一个按钮和一个标签,当按钮点下之后标签上的数字开始递增。首先,我们需要一个页面,也就是Cairngorm中的View部分:
01 | <?xml version= "1.0" encoding= "utf-8" ?> |
03 | xmlns:s= "library://ns.adobe.com/flex/spark" |
04 | xmlns:mx= "library://ns.adobe.com/flex/mx" minWidth= "955" minHeight= "600" |
05 | <SPAN style= "COLOR: #ff0000" >xmlns:model= "model.*" xmlns:control= "control.*" xmlns:business= "business.*" </SPAN> |
06 | creationComplete= "application1_creationCompleteHandler(event)" > |
09 | import com.adobe.cairngorm.control.CairngormEventDispatcher; |
10 | import control.CountEvent; |
11 | import control.MyFrontControl; |
12 | import flash.utils.setTimeout; |
13 | import model.MyModelLocator; |
14 | import mx.events.FlexEvent; |
17 | private function loggingHandler(evt:MouseEvent):void |
19 | var num:Num = new Num(); |
20 | num.startNum = MyModelLocator.getInstance().count; |
21 | var countEvent:CountEvent = new CountEvent(num); |
22 | <SPAN style= "COLOR: #ff0000" >CairngormEventDispatcher.getInstance().dispatchEvent(countEvent);</SPAN> |
25 | protected function application 1 _creationCompleteHandler(event:FlexEvent):void |
32 | <SPAN style= "COLOR: #ff0000" ><fx:Declarations> |
33 | <control:MyFrontControl/> |
34 | <business:MyServiceLocator/> |
35 | </fx:Declarations></SPAN> |
36 | <s:Label id= "lable" x= "430" y= "158" width= "66" height= "22" text= "{<SPAN style=" COLOR: #ff0000 ">MyModelLocator.getInstance().count</SPAN>}" /> |
37 | <s:Button id= "button" x= "430" y= "201" label= "start" width= "66" click= "loggingHandler(event)" /> |
当用户点击按钮之后,就会调用loggingHandler函数。这loggingHandler中声明了一个自定义Event——CountEvent。
03 | import com.adobe.cairngorm.control.CairngormEvent; |
07 | public class CountEvent <SPAN style= "COLOR: #ff0000" >extends CairngormEvent</SPAN> |
09 | public var num:Num = new Num(); |
10 | public function CountEvent(num:Num) |
12 | super (MyFrontControl.COUNT_EVENT); |
CountEvent的构造函数中有一句super(MyFrontControl.COUNT_EVENT),在上一篇中我们讲到FrontControl的作用是监听所有Event,其中COUNT_EVENT就是我们所定义的Event的type,记住,CairngormEvent也是继承自Event的。当然,COUNT_EVENT不是凭空产生的,是我们在自定义的FrontControl中定义的。自定义的FrontControl代码如下:
03 | import com.adobe.cairngorm.control.FrontController; |
04 | import command.CountCommand; |
06 | public class MyFrontControl extends FrontController |
08 | public static var COUNT_EVENT:String = "counting" ; |
09 | public function MyFrontControl() |
11 | this.addCommand(COUNT_EVENT,CountCommand); |
FrontControl管理所有的Event,监听它们并且接受处理它们,回想一下Observer Pattern,我们会在把所有的Observer对象存入Subject中,当事件发生之后Subject会在其内部的表中查找相应的Observer然后调用它们的notify方法。你可以用相同的方法去理解FrontControl的机制,试想,如果我有两个Event,那么FrontControl就应该这样写了:
03 | import com.adobe.cairngorm.control.FrontController; |
05 | import command.CountCommand; |
06 | import command.CountCommand 2 ; |
08 | public class MyFrontControl extends FrontController |
10 | public static var COUNT_EVENT:String = "counting" ; |
11 | public static var COUNT_EVENT 2: String = "counting2" ; |
12 | public function MyFrontControl() |
14 | this.addCommand(COUNT_EVENT,CountCommand); |
15 | this.addCommand(COUNT_EVENT 2 ,CountCommand 2 ); |
FrontControl相当于一个Subject的实例,它把所有需要监听的Event和其对应的Command名称加入到内部的列表,并且对所有的Event进行监听,当接受的Event之后它就会在内部列表中查找这个Event然后调用相应的Command类的execute()方法。
现在我们就可以很好地理解CairngormEventDispatcher.getInstance().dispatchEvent(countEvent)这句话了,Event被发送之后FrontControl处理之,现在我们来看FrontControl调用的Command是什么样的。
03 | import business.CountDelegate; |
04 | import com.adobe.cairngorm.commands.ICommand; |
05 | import com.adobe.cairngorm.control.CairngormEvent; |
06 | import control.CountEvent; |
07 | import model.MyModelLocator; |
08 | import mx.rpc.IResponder; |
09 | import mx.rpc.events.ResultEvent; |
12 | public class CountCommand <SPAN style= "COLOR: #ff0000" >implements ICommand, IResponder</SPAN> |
14 | public function CountCommand(){ |
17 | public function <SPAN style= "COLOR: #ff0000" >execute</SPAN>(event:CairngormEvent):void |
19 | <SPAN style= "COLOR: #ff0000" >var delegate:CountDelegate = new CountDelegate(this);</SPAN> |
20 | var countEvent:CountEvent = CountEvent(event); |
21 | delegate.count(countEvent.num); |
23 | public function <SPAN style= "COLOR: #ff0000" >result</SPAN>(data:Object):void |
25 | var result:Num = data as Num; |
26 | MyModelLocator.getInstance().num = result; |
27 | MyModelLocator.getInstance().count = result.startNum; |
29 | public function <SPAN style= "COLOR: #ff0000" >fault</SPAN>(info:Object):void |
我们看到了execute()方法,其实这个方法在接口ICommand中定义。在execute()方法中,Delegate被声明,并且相应的方法被调用。result()方法同样需引起注意,因为它决定了Delegate调用远程服务之后如何处理结果。记住,result()方法是在Delegate中调用的。fault()方法和result()一样,它们都在接口IResponder中定义。
我们接着说自定义的Delegate
03 | import com.adobe.cairngorm.business.ServiceLocator; |
04 | import flash.utils.clearTimeout; |
05 | import flash.utils.setTimeout; |
06 | import mx.rpc.IResponder; |
07 | import mx.rpc.events.ResultEvent; |
08 | import mx.rpc.remoting.RemoteObject; |
11 | public class CountDelegate |
13 | private var responder:IResponder; |
14 | private var counter:int; |
15 | private var remoteObject:RemoteObject; |
16 | public function CountDelegate(responder:IResponder) |
18 | this.responder = responder; |
20 | public function count(num:Num):void |
22 | counter = num.startNum; |
23 | <SPAN style= "COLOR: #ff0000" >remoteObject = ServiceLocator.getInstance().getRemoteObject( "counting" ); |
24 | remoteObject.addEventListener(ResultEvent.RESULT,OnResult);</SPAN> |
27 | private function counting():void |
29 | remoteObject.getOperation( "count" ).send( counter ); |
30 | flash.utils.setTimeout(counting, 1000 ); |
32 | private function OnResult(evt:ResultEvent):void |
34 | var result:Num = new Num(); |
35 | counter = evt.result as int; |
36 | result.startNum = counter ; |
37 | <SPAN style= "COLOR: #ff0000" >responder.result(result);</SPAN> |
这里我们以一个RemoteObject远程调用为例,首先,我们调用的远程服务在ServiceLocator中定义,可以通过remoteObject = ServiceLocator.getInstance().getRemoteObject("counting")来制定这个远程对象,"counting"是在ServiceLocator中定义的RemoteObject id(当然这个ServiceLocator也是我们自定义的,Cairngorm提供的ServiceLocator是一个单例模式的对象)。然后我们为这个远程对象添加ResultEvent的监听器。当我们收到远程调用的结果时,我们调用responder.result()执行在Command中实现的结果处理方法。
下面是我们自定义的ServiceLocator:
1 | <?xml version= "1.0" encoding= "utf-8" ?> |
3 | xmlns:s= "library://ns.adobe.com/flex/spark" |
4 | xmlns:mx= "library://ns.adobe.com/flex/mx" |
5 | xmlns:cairngorm= "com.adobe.cairngorm.business.*" > |
7 | <s:RemoteObject id= "counting" destination= "countingService" /> |
9 | </cairngorm:ServiceLocator> |
RemoteObject和Blazeds的配置就不解释了,再附上我们自定义的VO和JAVA服务端代码就完整了。
3 | import com.adobe.cairngorm.vo.IValueObject; |
4 | public class Num implements IValueObject |
6 | public var startNum:int; |
JAVA服务端代码
3 | public class CountingService { |
4 | public CountingService(){} |
5 | public int count(int num){ |