使用Cairngorm的第一步是建立框架结构的骨架,包括了三个对象:
Model Locater;
Service Locator;
Front Controller;
Model Locator:承载了组件之间的所有的传递的信息和数据,这是一个Bindable(可绑定的)对象。
Service Locator:定义了与数据源(Httpservice,Webservice,Remoteobject)之间通讯的界面。
Front Controller:建立播送事件(Dispatch event)和命令层(command)之间的对应关系(mapping)。
看一下相关的代码:
BuddyAppModelLocator.as:
- <EM>package com.ny.flex.cairngorm.model
- {
- import com.ny.flex.cairngorm.vo.User;
- import mx.collections.ArrayCollection;
- [Bindable]
- public class BuddyAppModelLocator
- {
- public var buddyList:ArrayCollection=new ArrayCollection();
- public var loginUser:User=new User();
- public var viewStackSelectedIndex :int = 0;
- static private var __instance:BuddyAppModelLocator=null;
- static public function getInstance():BuddyAppModelLocator
- {
- if(__instance == null)
- {
- __instance=new BuddyAppModelLocator();
- }
- return __instance;
- }
- }
- }
- </EM>
- <EM>package com.ny.flex.cairngorm.model
- {
- import com.ny.flex.cairngorm.vo.User;
- import mx.collections.ArrayCollection;
- [Bindable]
- public class BuddyAppModelLocator
- {
- public var buddyList:ArrayCollection=new ArrayCollection();
- public var loginUser:User=new User();
- public var viewStackSelectedIndex :int = 0;
- static private var __instance:BuddyAppModelLocator=null;
- static public function getInstance():BuddyAppModelLocator
- {
- if(__instance == null)
- {
- __instance=new BuddyAppModelLocator();
- }
- return __instance;
- }
- }
- }
- </EM>
package com.ny.flex.cairngorm.model { import com.ny.flex.cairngorm.vo.User; import mx.collections.ArrayCollection; [Bindable] public class BuddyAppModelLocator { public var buddyList:ArrayCollection=new ArrayCollection(); public var loginUser:User=new User(); public var viewStackSelectedIndex :int = 0; static private var __instance:BuddyAppModelLocator=null; static public function getInstance():BuddyAppModelLocator { if(__instance == null) { __instance=new BuddyAppModelLocator(); } return __instance; } } }
在Model Locator代码中,定义了三个public的变量,buddyList:用来存放由数据库获取的密友列表;loginUser:定义一个User类型对象;viewStackSelectedIndex:定义viewStack指向的视窗。
几乎所有的服务层返回的信息都需要在Model Locator中有一个相应的对象。
BuddyServiceLocator.mxml:
- <EM><EM><?xml version=”1.0″ encoding=”utf-8″?>
- <cairngorm:ServiceLocator xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:cairngorm=”http://www.adobe.com/2006/cairngorm“>
- <mx:RemoteObject id=”buddyRo“ destination=”flexmvcRO” >
- </mx:RemoteObject>
- </cairngorm:ServiceLocator>
- </EM></EM>
- <EM><EM><?xml version=”1.0″ encoding=”utf-8″?>
- <cairngorm:ServiceLocator xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:cairngorm=”http://www.adobe.com/2006/cairngorm“>
- <mx:RemoteObject id=”buddyRo“ destination=”flexmvcRO” >
- </mx:RemoteObject>
- </cairngorm:ServiceLocator>
- </EM></EM>
<?xml version=”1.0″ encoding=”utf-8″?> <cairngorm:ServiceLocator xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:cairngorm=”http://www.adobe.com/2006/cairngorm“> <mx:RemoteObject id=”buddyRo“ destination=”flexmvcRO” > </mx:RemoteObject> </cairngorm:ServiceLocator>
上述代码定义了程序将要调用的RemoteObject ,RemoteObject 所调用的Destination需要和remote_config.xml文件中的Destination相一致。在此,Destination的值为“flexmvcRO”。
BuddyListController.as:
- <EM><EM><STRONG>package com.ny.flex.cairngorm.control
- {
- import com.adobe.cairngorm.control.FrontController;
- import com.ny.flex.cairngorm.command.GetBuddyListCommand;
- import com.ny.flex.cairngorm.command.LoginCommand;
- import com.ny.flex.cairngorm.event.GetBuddyListEvent;
- import com.ny.flex.cairngorm.event.LoginEvent;
- public class BuddyListController extends FrontController
- {
- public function BuddyListController()
- {
- super();
- addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);
- addCommand(GetBuddyListEvent.GET_BUDDY_LIST_EVENT,
- GetBuddyListCommand);
- }
- }
- }
- </STRONG></EM></EM>
- <EM><EM><STRONG>package com.ny.flex.cairngorm.control
- {
- import com.adobe.cairngorm.control.FrontController;
- import com.ny.flex.cairngorm.command.GetBuddyListCommand;
- import com.ny.flex.cairngorm.command.LoginCommand;
- import com.ny.flex.cairngorm.event.GetBuddyListEvent;
- import com.ny.flex.cairngorm.event.LoginEvent;
- public class BuddyListController extends FrontController
- {
- public function BuddyListController()
- {
- super();
- addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);
- addCommand(GetBuddyListEvent.GET_BUDDY_LIST_EVENT,
- GetBuddyListCommand);
- }
- }
- }
- </STRONG></EM></EM>
package com.ny.flex.cairngorm.control { import com.adobe.cairngorm.control.FrontController; import com.ny.flex.cairngorm.command.GetBuddyListCommand; import com.ny.flex.cairngorm.command.LoginCommand; import com.ny.flex.cairngorm.event.GetBuddyListEvent; import com.ny.flex.cairngorm.event.LoginEvent; public class BuddyListController extends FrontController { public function BuddyListController() { super(); addCommand(LoginEvent.LOGIN_EVENT,LoginCommand); addCommand(GetBuddyListEvent.GET_BUDDY_LIST_EVENT, GetBuddyListCommand); } } }
很显然,上述的Controller代码是事件和命令的对应处理的地方。
如何能将这些乱七八糟的东西结合在一起?其Magic的地方是在主页(Main application)上,代码如下:
BuddList_Main_Cairngorm.mxml:
- <EM><EM><STRONG><?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml“ xmlns:service=”com.ny.flex.cairngorm.service.*“ xmlns:controller=”com.ny.flex.cairngorm.control.*” xmlns:views=”com.ny.flex.cairngorm.views.*” layout=”absolute“ width=”100%” height=”100%“>
- <mx:Script>
- <![CDATA[
- import com.ny.flex.cairngorm.model.BuddyAppModelLocator;
- [Bindable]
- public var myModel:BuddyAppModelLocator = BuddyAppModelLocator.getInstance();
- ]]>
- </mx:Script>
- <service:BuddyServiceLocator id=”myservice“/>
- <controller:BuddyListController id=”myController“/>
- <mx:HBox horizontalAlign=”center” verticalAlign=”top“ width=”100%” height=”100%” y=”0” x=”0“>
- <mx:ViewStack id=”viewStack“ resizeToContent=”true” selectedIndex=”{myModel.viewStackSelectedIndex}” >
- <views:LoginView />
- <views:BuddyListView/>
- </mx:ViewStack>
- </mx:HBox>
- </mx:Application>
- </STRONG></EM></EM>
- <EM><EM><STRONG><?xml version=”1.0″ encoding=”utf-8″?>
- <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml“ xmlns:service=”com.ny.flex.cairngorm.service.*“ xmlns:controller=”com.ny.flex.cairngorm.control.*” xmlns:views=”com.ny.flex.cairngorm.views.*” layout=”absolute“ width=”100%” height=”100%“>
- <mx:Script>
- <![CDATA[
- import com.ny.flex.cairngorm.model.BuddyAppModelLocator;
- [Bindable]
- public var myModel:BuddyAppModelLocator = BuddyAppModelLocator.getInstance();
- ]]>
- </mx:Script>
- <service:BuddyServiceLocator id=”myservice“/>
- <controller:BuddyListController id=”myController“/>
- <mx:HBox horizontalAlign=”center” verticalAlign=”top“ width=”100%” height=”100%” y=”0” x=”0“>
- <mx:ViewStack id=”viewStack“ resizeToContent=”true” selectedIndex=”{myModel.viewStackSelectedIndex}” >
- <views:LoginView />
- <views:BuddyListView/>
- </mx:ViewStack>
- </mx:HBox>
- </mx:Application>
- </STRONG></EM></EM>
<?xml version=”1.0″ encoding=”utf-8″?> <mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml“ xmlns:service=”com.ny.flex.cairngorm.service.*“ xmlns:controller=”com.ny.flex.cairngorm.control.*” xmlns:views=”com.ny.flex.cairngorm.views.*” layout=”absolute“ width=”100%” height=”100%“> <mx:Script> <![CDATA[ import com.ny.flex.cairngorm.model.BuddyAppModelLocator; [Bindable] public var myModel:BuddyAppModelLocator = BuddyAppModelLocator.getInstance(); ]]> </mx:Script> <service:BuddyServiceLocator id=”myservice“/> <controller:BuddyListController id=”myController“/> <mx:HBox horizontalAlign=”center” verticalAlign=”top“ width=”100%” height=”100%” y=”0” x=”0“> <mx:ViewStack id=”viewStack“ resizeToContent=”true” selectedIndex=”{myModel.viewStackSelectedIndex}” > <views:LoginView /> <views:BuddyListView/> </mx:ViewStack> </mx:HBox> </mx:Application>
现在用户可以建立视图组件,并从这些组件中播送事件:
LoginView.mxml:
- <EM><EM><STRONG><EM> <![CDATA[
- import com.ny.flex.cairngorm.event.LoginEvent;
- import com.ny.flex.cairngorm.vo.User;
- import mx.validators.Validator;
- private function login():void{
- if(Validator.validateAll(validators).length == 0){
- var loginUser:User = new User();
- loginUser.userName=username.text;
- loginUser.password=password.text;
- var loginEvent:LoginEvent = new LoginEvent();
- loginEvent.loginUser = loginUser;
- loginEvent.dispatch();
- }
- }
- ]]>
- </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>
- </EM></STRONG></EM></EM>
- <EM><EM><STRONG><EM> <![CDATA[
- import com.ny.flex.cairngorm.event.LoginEvent;
- import com.ny.flex.cairngorm.vo.User;
- import mx.validators.Validator;
- private function login():void{
- if(Validator.validateAll(validators).length == 0){
- var loginUser:User = new User();
- loginUser.userName=username.text;
- loginUser.password=password.text;
- var loginEvent:LoginEvent = new LoginEvent();
- loginEvent.loginUser = loginUser;
- loginEvent.dispatch();
- }
- }
- ]]>
- </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>
- </EM></STRONG></EM></EM>
<![CDATA[ import com.ny.flex.cairngorm.event.LoginEvent; import com.ny.flex.cairngorm.vo.User; import mx.validators.Validator; private function login():void{ if(Validator.validateAll(validators).length == 0){ var loginUser:User = new User(); loginUser.userName=username.text; loginUser.password=password.text; var loginEvent:LoginEvent = new LoginEvent(); loginEvent.loginUser = loginUser; loginEvent.dispatch(); } } ]]> </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>
每一个动作都需要建立一个相应的事件:
LoginEvent.as:
- <EM><EM><STRONG><EM>package com.ny.flex.cairngorm.event
- {
- import com.adobe.cairngorm.control.CairngormEvent;
- import com.ny.flex.cairngorm.vo.User;
- import flash.events.Event;
- public class LoginEvent extends CairngormEvent
- {
- public static var LOGIN_EVENT:String = “loginEvent”
- public var loginUser:User ;
- public function LoginEvent()
- {
- super(LOGIN_EVENT);
- }
- override public function clone() : Event
- {
- return new LoginEvent();
- }
- }
- }
- </EM></STRONG></EM></EM>
- <EM><EM><STRONG><EM>package com.ny.flex.cairngorm.event
- {
- import com.adobe.cairngorm.control.CairngormEvent;
- import com.ny.flex.cairngorm.vo.User;
- import flash.events.Event;
- public class LoginEvent extends CairngormEvent
- {
- public static var LOGIN_EVENT:String = “loginEvent”
- public var loginUser:User ;
- public function LoginEvent()
- {
- super(LOGIN_EVENT);
- }
- override public function clone() : Event
- {
- return new LoginEvent();
- }
- }
- }
- </EM></STRONG></EM></EM>
package com.ny.flex.cairngorm.event { import com.adobe.cairngorm.control.CairngormEvent; import com.ny.flex.cairngorm.vo.User; import flash.events.Event; public class LoginEvent extends CairngormEvent { public static var LOGIN_EVENT:String = “loginEvent” public var loginUser:User ; public function LoginEvent() { super(LOGIN_EVENT); } override public function clone() : Event { return new LoginEvent(); } } }
每一个事件都要对应于一个命令:
LoginCommand.as:
- <EM><EM><STRONG>package com.ny.flex.cairngorm.command
- {
- import com.adobe.cairngorm.commands.ICommand;
- import com.adobe.cairngorm.control.CairngormEvent;
- import com.ny.flex.cairngorm.event.LoginEvent;
- import com.ny.flex.cairngorm.model.BuddyAppModelLocator;
- import com.ny.flex.cairngorm.service.LoginDelegate;
- import com.ny.flex.cairngorm.vo.User;
- import mx.controls.Alert;
- import mx.rpc.IResponder;
- public class LoginCommand implements ICommand, IResponder
- {
- public function LoginCommand()
- {
- }
- public function execute(event:CairngormEvent):void
- {
- var loginEvent:LoginEvent = LoginEvent(event);
- var user:User = loginEvent.loginUser;
- var lgoinService :LoginDelegate
- = new LoginDelegate(this);
- lgoinService.authenticate(user);
- }
- public function result(event:Object):void
- {
- var authUser:User = User(event.result);
- BuddyAppModelLocator.getInstance().loginUser = authUser;
- BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1;
- }
- public function fault(info:Object):void
- {
- Alert.show(“Login Fail Error “);
- }
- }
- }
- </STRONG></EM></EM>
- <EM><EM><STRONG>package com.ny.flex.cairngorm.command
- {
- import com.adobe.cairngorm.commands.ICommand;
- import com.adobe.cairngorm.control.CairngormEvent;
- import com.ny.flex.cairngorm.event.LoginEvent;
- import com.ny.flex.cairngorm.model.BuddyAppModelLocator;
- import com.ny.flex.cairngorm.service.LoginDelegate;
- import com.ny.flex.cairngorm.vo.User;
- import mx.controls.Alert;
- import mx.rpc.IResponder;
- public class LoginCommand implements ICommand, IResponder
- {
- public function LoginCommand()
- {
- }
- public function execute(event:CairngormEvent):void
- {
- var loginEvent:LoginEvent = LoginEvent(event);
- var user:User = loginEvent.loginUser;
- var lgoinService :LoginDelegate
- = new LoginDelegate(this);
- lgoinService.authenticate(user);
- }
- public function result(event:Object):void
- {
- var authUser:User = User(event.result);
- BuddyAppModelLocator.getInstance().loginUser = authUser;
- BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1;
- }
- public function fault(info:Object):void
- {
- Alert.show(“Login Fail Error “);
- }
- }
- }
- </STRONG></EM></EM>
package com.ny.flex.cairngorm.command { import com.adobe.cairngorm.commands.ICommand; import com.adobe.cairngorm.control.CairngormEvent; import com.ny.flex.cairngorm.event.LoginEvent; import com.ny.flex.cairngorm.model.BuddyAppModelLocator; import com.ny.flex.cairngorm.service.LoginDelegate; import com.ny.flex.cairngorm.vo.User; import mx.controls.Alert; import mx.rpc.IResponder; public class LoginCommand implements ICommand, IResponder { public function LoginCommand() { } public function execute(event:CairngormEvent):void { var loginEvent:LoginEvent = LoginEvent(event); var user:User = loginEvent.loginUser; var lgoinService :LoginDelegate = new LoginDelegate(this); lgoinService.authenticate(user); } public function result(event:Object):void { var authUser:User = User(event.result); BuddyAppModelLocator.getInstance().loginUser = authUser; BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1; } public function fault(info:Object):void { Alert.show(“Login Fail Error “); } } }
然后,在Front Controller(前端控制器)中build对应关系:
addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);
命令层需要完成商务逻辑,用户需要在执行方法中加入商务逻辑代码:
- <EM><EM><STRONG> var lgoinService :LoginDelegate =
- new LoginDelegate(this);
- lgoinService.authenticate(user);
- </STRONG></EM></EM>
- <EM><EM><STRONG> var lgoinService :LoginDelegate =
- new LoginDelegate(this);
- lgoinService.authenticate(user);
- </STRONG></EM></EM>
var lgoinService :LoginDelegate = new LoginDelegate(this); lgoinService.authenticate(user);
Delegate(代表)用来通过服务层(Service Locator)调用数据源:
LoginDelegate.as:
- <EM><EM><STRONG><EM>package com.ny.flex.cairngorm.service
- {
- import com.adobe.cairngorm.business.ServiceLocator;
- import com.ny.flex.cairngorm.vo.User;
- import mx.rpc.IResponder;
- public class LoginDelegate
- {
- private var responder:IResponder;
- private var service:Object;
- public function LoginDelegate(responder :IResponder){
- this.service =
- ServiceLocator.getInstance()
- .getRemoteObject(“buddyRo”);
- this.responder = responder;
- }
- public function authenticate(user:User):void{
- var call:Object = service.authenticate(user);
- call.addResponder(responder);
- }
- }
- }
- </EM></STRONG></EM></EM>
- <EM><EM><STRONG><EM>package com.ny.flex.cairngorm.service
- {
- import com.adobe.cairngorm.business.ServiceLocator;
- import com.ny.flex.cairngorm.vo.User;
- import mx.rpc.IResponder;
- public class LoginDelegate
- {
- private var responder:IResponder;
- private var service:Object;
- public function LoginDelegate(responder :IResponder){
- this.service =
- ServiceLocator.getInstance()
- .getRemoteObject(“buddyRo”);
- this.responder = responder;
- }
- public function authenticate(user:User):void{
- var call:Object = service.authenticate(user);
- call.addResponder(responder);
- }
- }
- }
- </EM></STRONG></EM></EM>
package com.ny.flex.cairngorm.service { import com.adobe.cairngorm.business.ServiceLocator; import com.ny.flex.cairngorm.vo.User; import mx.rpc.IResponder; public class LoginDelegate { private var responder:IResponder; private var service:Object; public function LoginDelegate(responder :IResponder){ this.service = ServiceLocator.getInstance() .getRemoteObject(“buddyRo”); this.responder = responder; } public function authenticate(user:User):void{ var call:Object = service.authenticate(user); call.addResponder(responder); } } }
返回的结果将回复到命令层(LoginCommand.as)的结果方法中,在此方法中Model被更新,然后数据被绑定到结果视图上:
LoginCommand.as:
- <EM><EM><STRONG> public function result(event:Object):void
- {
- var authUser:User = User(event.result);
- BuddyAppModelLocator.getInstance().loginUser
- = authUser;
- BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1;
- }
- </STRONG></EM></EM>
- <EM><EM><STRONG> public function result(event:Object):void
- {
- var authUser:User = User(event.result);
- BuddyAppModelLocator.getInstance().loginUser
- = authUser;
- BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1;
- }
- </STRONG></EM></EM>