您的位置:首页 > 大数据 > 人工智能

Flex 开发架构(三): MVC框架-Flex Cairngorm

2010-03-10 13:17 363 查看

Flex 开发架构(三): MVC框架-Flex Cairngorm

原创作者: houwei 阅读:1455次 评论:0条 更新时间:2009-02-12 收藏

有没有听说过这个奇怪的词汇:“Cairngorm”?如果你的回答是“No” && 你是Flex程序员,哪你就看看自己是不是住在一个井底。J

Cairngorm是Flex的一个MVC框架结构,名字取自苏格兰的一个山脉。(kao,如果是我建立一个自己的框架结构,我就取名叫:“天安门”。)

有关这个框架,在网络上有很多图表用来讨论。下面是我所理解的框架图表:



使用Cairngorm的第一步是建立框架结构的骨架,包括了三个对象:

Model Locater
Service Locator
Front Controller

Model Locator:承载了组件之间的所有的传递的信息和数据,这是一个Bindable(可绑定的)对象。

Service Locator:定义了与数据源(Httpservice,Webservice,Remoteobject)之间通讯的界面。

Front Controller:建立播送事件(Dispatch event)和命令层(command)之间的对应关系(mapping)。

看一下相关的代码:

BuddyAppModelLocator.as:

Xml代码



<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:

Xml代码



<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:

Xml代码



<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)上,代码如下:

[b]BuddList_Main_Cairngorm.mxml:[/b]

Xml代码



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


现在用户可以建立视图组件,并从这些组件中播送事件:

[b]LoginView.mxml:[/b]

Xml代码



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


每一个动作都需要建立一个相应的事件:

[b]LoginEvent.as:[/b]

Xml代码



<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();
}
}
}


每一个事件都要对应于一个命令:
[b]LoginCommand.as:[/b]

Xml代码



<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对应关系:

[b]addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);[/b]

命令层需要完成商务逻辑,用户需要在执行方法中加入商务逻辑代码:

Xml代码



<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)调用数据源:

[b]LoginDelegate.as:[/b]

Xml代码



<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被更新,然后数据被绑定到结果视图上:
[b]LoginCommand.as:[/b]

Xml代码



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

            public function result(event:Object):void
{
var authUser:User = User(event.result);
BuddyAppModelLocator.getInstance().loginUser
= authUser;
BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1;
}


其它的视图工作流程同上,整个密友列表项目的结构如下图所示:




使用Cairngorm开发应用项目Layer,测试性高。并且使得程序员更专业化。
但这个框架的确很不容易学习和维护,那么有没有更好的方法简化它?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: