Flex MVC框架-Flex_Cairngorm

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

 

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

 

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

                       

 

 

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

 

Model Locater

Service Locator

Front Controller

 

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

 

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

 

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

 

看一下相关的代码:

 

BuddyAppModelLocator.as:

 

Xml代码

1         <em>package com.ny.flex.cairngorm.model 

2         { 

3               import com.ny.flex.cairngorm.vo.User; 

4                 

5               import mx.collections.ArrayCollection; 

6                 

7               [Bindable] 

8               public class BuddyAppModelLocator 

9               { 

10                 public var buddyList:ArrayCollection=new ArrayCollection(); 

11                 public var loginUser:User=new User(); 

12                 public var viewStackSelectedIndex :int = 0; 

13                   

14                 static private var __instance:BuddyAppModelLocator=null; 

15                   

16                 static public function getInstance():BuddyAppModelLocator 

17                 { 

18                       if(__instance == null) 

19                       { 

20                             __instance=new BuddyAppModelLocator(); 

21                       } 

22                       return __instance; 

23                 } 

24           } 

25     } 

26     </em> 





Model Locator代码中,定义了三个public的变量,buddyList:用来存放由数据库获取的密友列表;loginUser:定义一个User类型对象;viewStackSelectedIndex:定义viewStack指向的视窗。

几乎所有的服务层返回的信息都需要在Model Locator中有一个相应的对象。





BuddyServiceLocator.mxml:

 

Xml代码

27     <em><em><?xml version=”1.0″ encoding=”utf-8″?> 

28     <cairngorm:ServiceLocator xmlns:mx=”http://www.adobe.com/2006/mxml” xmlns:cairngorm=”http://www.adobe.com/2006/cairngorm“> 

29           <mx:RemoteObject id=”buddyRo“  destination=”flexmvcRO” > 

30                   

31           </mx:RemoteObject> 

32     </cairngorm:ServiceLocator> 

33     </em></em> 



 

上述代码定义了程序将要调用的RemoteObject RemoteObject 所调用的Destination需要和remote_config.xml文件中的Destination相一致。在此,Destination的值为“flexmvcRO

 

 

 

BuddyListController.as:

 



 

Xml代码

34     <em><em><strong>package com.ny.flex.cairngorm.control 

35     { 

36           import com.adobe.cairngorm.control.FrontController; 

37           import com.ny.flex.cairngorm.command.GetBuddyListCommand; 

38           import com.ny.flex.cairngorm.command.LoginCommand; 

39           import com.ny.flex.cairngorm.event.GetBuddyListEvent; 

40           import com.ny.flex.cairngorm.event.LoginEvent; 

41        

42           public class BuddyListController extends FrontController 

43           { 

44                 public function BuddyListController() 

45                 { 

46                       super(); 

47                       addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);       

48                       addCommand(GetBuddyListEvent.GET_BUDDY_LIST_EVENT, 

49     GetBuddyListCommand); 

50                 } 

51                   

52           } 

53     } 

54     </strong></em></em> 



很显然,上述的Controller代码是事件和命令的对应处理的地方。

 

如何能将这些乱七八糟的东西结合在一起?其Magic的地方是在主页(Main application)上,代码如下:

 

BuddList_Main_Cairngorm.mxml:

 

Xml代码

55     <em><em><strong><?xml version=”1.0″ encoding=”utf-8″?> 

56     <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%“> 

57     <mx:Script> 

58           <![CDATA[

59                 import com.ny.flex.cairngorm.model.BuddyAppModelLocator;

60           [Bindable]

61           public var myModel:BuddyAppModelLocator = BuddyAppModelLocator.getInstance();

62           ]]> 

63     </mx:Script> 

64        

65           <service:BuddyServiceLocator id=”myservice“/> 

66           <controller:BuddyListController id=”myController“/> 

67        

68         <mx:HBox  horizontalAlign=”center” verticalAlign=”top“  width=”100%” height=”100%” y=”0” x=”0“> 

69         <mx:ViewStack id=”viewStack“  resizeToContent=”true” selectedIndex=”{myModel.viewStackSelectedIndex}” > 

70             <views:LoginView  /> 

71             <views:BuddyListView/> 

72         </mx:ViewStack> 

73         </mx:HBox> 

74     </mx:Application> 

75     </strong></em></em> 





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



LoginView.mxml:

 

Xml代码

76     <em><em><strong><em>      <![CDATA[

77                 import com.ny.flex.cairngorm.event.LoginEvent;

78                 import com.ny.flex.cairngorm.vo.User;

79                 import mx.validators.Validator;

80                 private function login():void{

81                       if(Validator.validateAll(validators).length == 0){

82                             var loginUser:User = new User();

83                             loginUser.userName=username.text;

84                             loginUser.password=password.text;

85                             var loginEvent:LoginEvent = new LoginEvent();

86                             loginEvent.loginUser = loginUser;

87                             loginEvent.dispatch();

88                       }   

89                 }

90           ]]> 

91     </mx:Script> 

92        

93      <!–  Validators–> 

94      <mx:Array id=”validators“> 

95         <mx:StringValidator  id=”userNameValidator” source=”{username}“  property=”text“  required=”true“/> 

96         <mx:StringValidator  id=”passwordValidator” source=”{password}“  property=”text” required=”true” /> 

97      </mx:Array>     

98        

99        

100  <mx:Form id=”loginForm” x=”0” y=”0“> 

101            <mx:FormItem label=”Username:” > 

102                 <mx:TextInput id=”username” /> 

103             </mx:FormItem> 

104             <mx:FormItem label=”Password:” > 

105                 <mx:TextInput id=”password” displayAsPassword=”true” /> 

106             </mx:FormItem> 

107             <mx:FormItem direction=”horizontal” verticalGap=”15” paddingTop=”5” width=”170“> 

108                 <mx:Button id=”loginBtn” label=”Login” click=”login()”/> 

109             </mx:FormItem> 

110      </mx:Form> 

111          

112  </mx:Panel> 

113  </em></strong></em></em> 

 



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









LoginEvent.as:

 

Xml代码

114  <em><em><strong><em>package com.ny.flex.cairngorm.event 

115  { 

116        import com.adobe.cairngorm.control.CairngormEvent; 

117        import com.ny.flex.cairngorm.vo.User; 

118          

119        import flash.events.Event; 

120     

121        public class LoginEvent extends CairngormEvent 

122        { 

123              public static var LOGIN_EVENT:String = “loginEvent” 

124              public  var  loginUser:User ; 

125                

126              public function LoginEvent() 

127              { 

128                    super(LOGIN_EVENT); 

129              } 

130     

131              override public function clone() : Event 

132              { 

133                    return new LoginEvent();  

134              } 

135        } 

136  } 

137  </em></strong></em></em> 

 



每一个事件都要对应于一个命令:

LoginCommand.as:



 

 

Xml代码

138  <em><em><strong>package com.ny.flex.cairngorm.command 

139  { 

140        import com.adobe.cairngorm.commands.ICommand; 

141        import com.adobe.cairngorm.control.CairngormEvent; 

142        import com.ny.flex.cairngorm.event.LoginEvent; 

143        import com.ny.flex.cairngorm.model.BuddyAppModelLocator; 

144        import com.ny.flex.cairngorm.service.LoginDelegate; 

145        import com.ny.flex.cairngorm.vo.User; 

146          

147        import mx.controls.Alert; 

148        import mx.rpc.IResponder; 

149     

150        public class LoginCommand implements ICommand, IResponder 

151        { 

152              public function LoginCommand() 

153              { 

154              } 

155     

156              public function execute(event:CairngormEvent):void 

157              { 

158                    var loginEvent:LoginEvent = LoginEvent(event); 

159                    var user:User = loginEvent.loginUser; 

160                    var lgoinService :LoginDelegate  

161  =  new LoginDelegate(this); 

162                    lgoinService.authenticate(user); 

163              } 

164                

165              public function result(event:Object):void 

166              { 

167                    var authUser:User = User(event.result); 

168                    BuddyAppModelLocator.getInstance().loginUser = authUser; 

169                    BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1; 

170              } 

171                

172              public function fault(info:Object):void 

173              { 

174                    Alert.show(“Login Fail Error “); 

175              } 

176                

177        } 

178  } 

179  </strong></em></em> 













然后,在Front Controller(前端控制器)中build对应关系:

 

 addCommand(LoginEvent.LOGIN_EVENT,LoginCommand);

 

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

 

Xml代码

180  <em><em><strong>                  var lgoinService :LoginDelegate =   

181                                              new LoginDelegate(this); 

182                    lgoinService.authenticate(user); 

183  </strong></em></em> 



Delegate(代表)用来通过服务层(Service Locator)调用数据源:

 

LoginDelegate.as:

 

Xml代码

184  <em><em><strong><em>package com.ny.flex.cairngorm.service 

185  { 

186        import com.adobe.cairngorm.business.ServiceLocator; 

187        import com.ny.flex.cairngorm.vo.User; 

188          

189        import mx.rpc.IResponder; 

190          

191        public class LoginDelegate 

192        { 

193              private var responder:IResponder; 

194              private var service:Object; 

195                

196              public function LoginDelegate(responder :IResponder){ 

197                this.service =  

198                             ServiceLocator.getInstance() 

199                                          .getRemoteObject(“buddyRo”); 

200                this.responder = responder; 

201              } 

202                

203              public function  authenticate(user:User):void{ 

204                    var call:Object = service.authenticate(user); 

205                    call.addResponder(responder); 

206              } 

207        } 

208  } 

209     

210  </em></strong></em></em> 

 





返回的结果将回复到命令层(LoginCommand.as)的结果方法中,在此方法中Model被更新,然后数据被绑定到结果视图上:

LoginCommand.as:

 

Xml代码

211  <em><em><strong>            public function result(event:Object):void 

212              { 

213                    var authUser:User = User(event.result); 

214                    BuddyAppModelLocator.getInstance().loginUser 

215                                                                                      = authUser; 

216                          BuddyAppModelLocator.getInstance().viewStackSelectedIndex=1; 

217              } 

218  </strong></em></em> 





 





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

 

 

使用Cairngorm开发应用项目Layer,测试性高。并且使得程序员更专业化。

但这个框架的确很不容易学习和维护,那么有没有更好的方法简化它?

 

来看看:咔嚓Front ControllerCairngorm



 

posted @ 2013-01-10 10:53  Ada zheng  阅读(248)  评论(0编辑  收藏  举报