代码改变世界

Flex 开发架构(四): 去除FrontController 的Cairngorm

2008-10-13 23:45  宝宝合凤凰  阅读(476)  评论(0)    收藏  举报

Flex 开发架构(四): 去除FrontController 的Cairngorm

关键字: flex,cairngorm, frontcontroller

http://houwei.javaeye.com/blog/223520

正如在使用Cairngorm时,视图中的每一个动作都播送一个事件,每个播送出去的事件都需要建立相应的命令代码来处理事件。并且需要在FrontController中对应他们的关系。例如下面的简单流程:

Loginvew.xml —> action login() —>dispatch LoginEvent —>Handled by LoginCommand —>mapping LoginEvent and LoginCommand in FrontController.

在不考虑商务层代码的情况下,当用户建立然后新的动作时,就需要建立2个新的代码,修改Controller代码。

那么如何简化Cairngorm,我的方法是去掉FrontController,取而代之的是Service Façade,其框架图如下所示:

 

 

在上图中,视图不再播送如何事件,而是直接调用Service Façade。而Service Façade则直接调用商务委托层与服务器端通讯(如Remote Object等),然后商务委托处理结果并更新Model Locator,最后Model Locator通过绑定(Binding)更新视窗中的结果。

 

看一下被改变的代码:

ServiceFacade.as:

 

Xml代码 复制代码
  1. package com.ny.flex.cairngorm.no_fc.service   
  2. {   
  3.     import com.ny.flex.cairngorm.no_fc.vo.User;   
  4.        
  5.     public class ServiceFacade   
  6.     {   
  7.         private static var _serviceFacade:ServiceFacade = null;   
  8.            
  9.         public function ServiceFacade(privateClass:PrivateClass)   
  10.         {   
  11.             if(ServiceFacade._serviceFacade == null){   
  12.                 ServiceFacade._serviceFacade = this;   
  13.             }   
  14.         }   
  15.         public static function getInstance():ServiceFacade {   
  16.             if(_serviceFacade == null){   
  17.                 _serviceFacade = new ServiceFacade(new PrivateClass);   
  18.             }   
  19.             return _serviceFacade;   
  20.         }   
  21.            
  22.         public function authenticate(user:User):void{   
  23.             LoginDelegate.getInstance().authenticate(user);   
  24.         }   
  25.         public function  getBuddyList():void{   
  26.             BuddyListDelegate.getInstance().getBuddyList();   
  27.         }   
  28.     }   
  29. }   
  30.   
  31. class  PrivateClass{}  
package com.ny.flex.cairngorm.no_fc.service
{
import com.ny.flex.cairngorm.no_fc.vo.User;
public class ServiceFacade
{
private static var _serviceFacade:ServiceFacade = null;
public function ServiceFacade(privateClass:PrivateClass)
{
if(ServiceFacade._serviceFacade == null){
ServiceFacade._serviceFacade = this;
}
}
public static function getInstance():ServiceFacade {
if(_serviceFacade == null){
_serviceFacade = new ServiceFacade(new PrivateClass);
}
return _serviceFacade;
}
public function authenticate(user:User):void{
LoginDelegate.getInstance().authenticate(user);
}
public function  getBuddyList():void{
BuddyListDelegate.getInstance().getBuddyList();
}
}
}
class  PrivateClass{}

  

ServiceFacade提供了对所有商务逻辑为一体的界面,视窗的行为(Action)仅仅调用façade,例如下面代码中的Login的动作。

Loginvew.xml

 

 

Xml代码 复制代码
  1. private function login():void{   
  2.         if(Validator.validateAll(validators).length == 0){   
  3.             var loginUser:User = new User();   
  4.             loginUser.userName=username.text;   
  5.             loginUser.password=password.text;   
  6.             <SPAN style="COLOR: #ff6600"><STRONG><EM>serviceFacade.authenticate(loginUser);</EM></STRONG></SPAN>  
  7.         }      
  8.     }  
	private function login():void{
if(Validator.validateAll(validators).length == 0){
var loginUser:User = new User();
loginUser.userName=username.text;
loginUser.password=password.text;
serviceFacade.authenticate(loginUser);
}
}

 

函数 serviceFacade.authenticate(loginUser)如下:

 

 

Xml代码 复制代码
  1. public function authenticate(user:User):void{   
  2.     <SPAN style="COLOR: #ff6600"><STRONG><EM>LoginDelegate.</EM></STRONG></SPAN>getInstance().authenticate(user);   
  3. }  
		public function authenticate(user:User):void{
LoginDelegate.getInstance().authenticate(user);
}

  

 

ServiceFacade使用LoginDelegate 来真正实现Business Logic:

 

 

 

 

 

 LoginDelegate.as:

 

 

Xml代码 复制代码
  1. package com.ny.flex.cairngorm.no_fc.service   
  2. {   
  3.     import com.ny.flex.cairngorm.no_fc.*;   
  4.     import com.ny.flex.cairngorm.no_fc.vo.User;   
  5.        
  6.     import mx.rpc.IResponder;   
  7.     import mx.rpc.Responder;   
  8.     import mx.rpc.events.ResultEvent;   
  9.        
  10.     public class LoginDelegate extends BaseDelegate    
  11.     {   
  12.         private static  var _loginDelegate:LoginDelegate = null;   
  13.            
  14.         public function LoginDelegate(privateClass:PrivateClass){   
  15.             if(LoginDelegate._loginDelegate == null ){   
  16.                 LoginDelegate._loginDelegate = this;   
  17.             }   
  18.            
  19.         }   
  20.            
  21.         public  static function  getInstance():LoginDelegate{   
  22.             if(_loginDelegate == null){   
  23.                 _loginDelegate = new LoginDelegate(new PrivateClass);   
  24.             }   
  25.             return  _loginDelegate;   
  26.         }   
  27.            
  28.         public function <SPAN style="COLOR: #ff6600"><STRONG><EM> authenticate</EM></STRONG></SPAN>(user:User):void{   
  29.             var responder:IResponder = new Responder(onResult_Authenticate,fault);   
  30.             var call:Object = service.authenticate(user);   
  31.             call.addResponder(responder);   
  32.         }   
  33.            
  34.         private function onResult_Authenticate(event:ResultEvent):void{   
  35.             var authUser:User = event.result as User;   
  36.             model.loginUser = authUser;   
  37.             model.viewStackSelectedIndex = 1;   
  38.         }   
  39.        
  40.     }   
  41. }   
  42.   
  43. class PrivateClass{}  
package com.ny.flex.cairngorm.no_fc.service
{
import com.ny.flex.cairngorm.no_fc.*;
import com.ny.flex.cairngorm.no_fc.vo.User;
import mx.rpc.IResponder;
import mx.rpc.Responder;
import mx.rpc.events.ResultEvent;
public class LoginDelegate extends BaseDelegate
{
private static  var _loginDelegate:LoginDelegate = null;
public function LoginDelegate(privateClass:PrivateClass){
if(LoginDelegate._loginDelegate == null ){
LoginDelegate._loginDelegate = this;
}
}
public  static function  getInstance():LoginDelegate{
if(_loginDelegate == null){
_loginDelegate = new LoginDelegate(new PrivateClass);
}
return  _loginDelegate;
}
public function  authenticate(user:User):void{
var responder:IResponder = new Responder(onResult_Authenticate,fault);
var call:Object = service.authenticate(user);
call.addResponder(responder);
}
private function onResult_Authenticate(event:ResultEvent):void{
var authUser:User = event.result as User;
model.loginUser = authUser;
model.viewStackSelectedIndex = 1;
}
}
}
class PrivateClass{}

  

 

上面的authenticate(user) 实现于后台通讯并处理结果,更新Model Locator

 

其他的视图和相应的处理方法 与上面类似。

 

 

 

这个解决方案简化了Cairngorm的框架,使得代码更易于理解。而且,彻底摆脱了 无味的dispatcher,frontcontroller 和command。 编码效率会提高 并且易于调试。

 

但其弱点是显而易见的:它违犯了解耦的(就是使得设计程序耦合性尽可能的降低)设计规范,使得界面上的行为(Action)和Serivce Façade产生了耦合关系。

 

在最后一篇中我将讨论下一个Flex 开发的热点:Mate-标签化的框架。