`
iMzw
  • 浏览: 195869 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Flex之使用Cairngorm(4) - Cairngorm Extensions

阅读更多
Previous Posts:
1.准备工作 http://nealmi.iteye.com/blog/164867
2.使用ModelLocator http://nealmi.iteye.com/blog/164879
3.Command & Event http://nealmi.iteye.com/blog/177370

Cairgorm Step By Step教程[推荐]
http://www.davidtucker.net/category/cairngorm/(英文)

下载源码:
后台指向我的Google App Engine 程序, 你可以暂时不关心后台, 直接导入到FlexBuilder里运行.
http://nealmi.iteye.com/topics/download/2e854ac3-89b2-3f15-814b-e4317380608e

就我个人来说,Cairngorm有两个致命的问题,直接影响到我是否使用它.
1.不支持通知视图.
Cairngorm2.1之前可以用ViewHelper 和 ViewLocator,但是自从Cairngorm2.1开始已经不推荐了.而且 ViewHelper和ViewLocator 方式本身就违反MVC.
2.不支持子Controller.

所以我选择了使用 UM Cairngorm Extensions. http://code.google.com/p/flexcairngorm/

Refactor To UM Cairngorm Extensions:

1.重构Event.继承com.universalmind.cairngorm.events.UMEvent.
在构造函数里接受一个IResponder类型的参数(用作通知视图), UMEvent 本身带有一个data属性.
import com.universalmind.cairngorm.events.UMEvent;

public class LoginEvent extends UMEvent{
		
		public static const LOGIN:String = "login";
		
		public function LoginEvent(user:UserVO=null, callbacks:IResponder=null){
			super(LOGIN, callbacks, true, true, user);
		}
		
		public function get user():UserVO{
			trace("LoginEvent - user() - " +  data);
			return data as UserVO;
		}


2.重构Controller.继承com.universalmind.cairngorm.control.FrontController.增加对子Controller的支持,可以通过addSubController(..)方法来添加子Controller.这样可以每个独立的模块有独立MVC结构.
       import com.universalmind.cairngorm.control.FrontController;
	

	public class UserController extends FrontController	{
		public function UserController(){
			super();
			this.init();
		}
		
		private function init():void{
			this.addCommand(LoginEvent.LOGIN, UserCommand);
			//Add sub controller via addSubController(...);
		}
	}


3.重构Command.继承com.universalmind.cairngorm.commands.Command.这里通过用了一种可以减少类文件的写法.(cairngorm继承了JEE中大量的垃圾.类爆炸就是其中之一).
public class UserCommand extends Command{
		
		override public function execute(event:CairngormEvent):void{
			super.execute(event);
			
			switch(event.type){
				case LoginEvent.LOGIN:
					doLogin(event as LoginEvent);
					break;
				case RegistrationEvent.REGISTRATION:
					doRegistration(event as RegistrationEvent);
					break;
				default:
					trace("Unkonw event type [" + event.type +"]");
			}
		}
		
		private function doLogin(event:LoginEvent):void{
			var delegate:UserDelegate = new UserDelegate(event.callbacks);
			trace("LoginCommand - doLogin - "  + event.user);
			delegate.login(event.user);
		}
		
		private function doRegistration(event:RegistrationEvent):void{
			var delegate:UserDelegate = new UserDelegate(event.callbacks);
			trace("LoginCommand - doLogin - "  + event.user);
			//delegate.register(event.user);
		}


3.重构Delegate, 继承com.universalmind.cairngorm.business.Delegate.

public function UserDelegate(commandHandlers:IResponder=null){
//userService 声明在Services.mxml里.
			super(commandHandlers, "userService");
		}
		
		public function login(user:UserVO):void {
            trace("UserDelegate.login() - " + user);
            
//这里多加了一层,你可以在这里将服务器返回的结果加以处理,比如:将XML结果组装成Value Object, 过滤掉某些数据等.
            var token: AsyncToken = service.login(user.loginName, user.password);
            var callbacks:Callbacks = new Callbacks(resultNotifyer, faultNotifyer);
            

            prepareHandlers(token, callbacks);
        }
        
        
        private function resultNotifyer(event:ResultEvent):void{
        	//Alert.show(event.result + "","result");
        	trace("resultNotifyer - " + event );
        	
        	// You can do something like filter data at here. eg: decode json .
        	//  Code sample -  Decode json:
        	//  ------------------------------
        	//  var rawData:String = event.result;
        	//  var obj:Object = JSON.decode(rawData);
        	//  var e:ResultEvent = new ResultEvent()
        	//  e.resulte = obj;
        	//  notifyCaller(e);
        	
//通知视图,也可以在Command里执行.
        	notifyCaller(event);
        }
        
        private function faultNotifyer(event:FaultEvent):void{
        	//Alert.show(event.fault+"","fault");
        	trace("faultNotifyer - " + event );
        	notifyCaller(event);
        }        


6.View代码.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
			import mx.utils.StringUtil;
			import com.universalmind.cairngorm.events.Callbacks;
			import net.imzw.UserManagerDemo.event.LoginEvent;
			import mx.rpc.IResponder;
			import mx.rpc.events.ResultEvent;
			import mx.rpc.events.FaultEvent;
			import net.imzw.UserManagerDemo.vo.UserVO;
			import net.imzw.UserManagerDemo.model.UserManagerModelLocator;
			import mx.controls.Alert;
			
			private var modelLocator:UserManagerModelLocator = UserManagerModelLocator.getInstance();
			
			private function login(e:MouseEvent):void{
				//组装Callback.
				var callbacks:IResponder = new Callbacks(resultHandler, faultHandler);
				var user:UserVO = new UserVO(StringUtil.trim(loginNameTextInput.text), 
													StringUtil.trim(passwordTextInput.text));
				var loginEvent:LoginEvent = new LoginEvent(user, callbacks);
				trace("doSignIn - " + loginEvent);
				
				loginEvent.dispatch();
			} 
			private function resultHandler(event:ResultEvent):void{
				
				if(event.result == null){
					Alert.show("登录名或密码错误.", "Error");
					
//登录名或密码错误时,设置焦点到用户名TextInput,标准的Cairgorm很难做到指点.	
				loginNameTextInput.setFocus();
				}else{
					trace(event.result.loginName + "");
					// Here should can simple like following code, but I got an error. 
					// May be case by fields mismatch between flex and backend. 
					
					// modelLocator.currentUser = event.result as UserVO;
					
					var user:UserVO =new  UserVO(event.result.loginName);
					trace(user.loginName);
					modelLocator.currentUser = user;
					trace(modelLocator.currentUser.loginName);
					
					modelLocator.workflowState = UserManagerModelLocator.MAIN_SCREEN;
					
					reset();
				}
			}
			
			private function faultHandler(event:FaultEvent):void{
				trace(event.message + "");
				
				Alert.show( "服务器错误, 请稍候再试.", "Error");
			}
			
			private function reset():void{
				loginNameTextInput.text = "";
				passwordTextInput.text = "";
			}
		]]>
	</mx:Script>
	<mx:Form defaultButton="{loginButton}" borderSides="left right top bottom" borderStyle="solid" borderColor="green">
		<mx:FormHeading label="Please Login" />
		<mx:FormItem label="LoginName">
			<mx:TextInput id="loginNameTextInput" />
		</mx:FormItem>
		<mx:FormItem label="Password">
			<mx:TextInput id="passwordTextInput" displayAsPassword="true"/>
		</mx:FormItem>
		<mx:HBox horizontalAlign="right" width="100%">
			<mx:Button id="loginButton" click="{login(event)}" label="Login" />
		</mx:HBox>
	</mx:Form>
</mx:VBox>




6.注意Value Object的写法.要实现com.universalmind.cairngorm.vo.IValueObject接口.实现copyFrom 和Clone方法.
package net.imzw.UserManagerDemo.vo{
	
	import com.universalmind.cairngorm.vo.IValueObject;
	
	[Bindable]
	public class UserVO implements IValueObject{
		public var id:Number;
		public var loginName:String;
		public var password:String;
		
		public function UserVO( loginName:String=null, password:String=null ){
			this.loginName = loginName;
			this.password = password;
		}

		public function copyFrom(src:*):*{
			this.loginName = src.loginName;
			this.password = src.password;
		}
		
		public function clone():*{
			return new UserVO(loginName, password);
		}
		
		public function equals(anotherUser:*):Boolean{
			if(null == anotherUser) return false;
			
			if(id == anotherUser.id && loginName == anotherUser.loginName){
				return true;
			}
			return false;
		}
		
		public function toString():String{
			return "User[loginName:"+loginName+"]";
		}
	}
}


以上只是粗略的介绍.有什么问题可以联系我通过邮件 imzw.net+javaeye at gmail.com.

-------------
IT'S NEAL.
4
0
分享到:
评论

相关推荐

    用Flex+Java进行软件开发速成篇

    Cairngorm Extensions是一个流行的Flex MVC框架,它简化了Flex应用程序的设计和开发过程。 - **Model**: 用于管理数据模型和业务逻辑。 - **View**: 负责用户界面的展示。 - **Controller**: 作为模型和视图之间的...

    flex as资料

    通过对《Effectively Using Cairngorm Extensions》的深入学习,开发者不仅可以掌握Cairngorm框架的基本用法,还能理解如何通过扩展优化其性能,提升Flex和AS3应用的开发水平。这将对提升个人的技能树和项目的成功...

    LTspice仿真:LDO电源电路学习与实践的利器

    内容概要:本文详细介绍了如何利用LTspice进行LDO(低压差线性稳压器)电源电路的仿真。首先讲解了如何导入LDO模型并配置仿真环境,接着深入探讨了瞬态分析、相位裕度、电源抑制比(PSRR)等关键仿真的具体步骤和注意事项。文中提供了多个实用的操作技巧,如通过调整补偿电容优化相位裕度,以及使用.step param命令批量测试不同参数的影响。此外,还分享了一些常见的仿真误区及其解决方法,帮助读者更好地理解和掌握LDO的设计与调试。 适合人群:电子工程专业学生、电源电路设计初学者、希望深入了解LDO特性的工程师。 使用场景及目标:适用于希望通过仿真工具提高LDO设计技能的人群。主要目标是掌握LDO的基本工作原理,学会使用LTspice进行各种类型的仿真分析,从而优化电路设计,确保系统的稳定性和性能。 其他说明:文章不仅提供详细的仿真步骤和技术细节,还附带了作者的实际经验和常见问题解决方案,使读者能够在实践中不断改进自己的设计思路。

    渝安集团员工职业发展通道设计方案.ppt

    渝安集团员工职业发展通道设计方案.ppt

    新能源电动汽车VCU与BMS的HIL硬件在环仿真技术及其模块化建模

    内容概要:本文详细介绍了新能源电动汽车中VCU(整车控制器)和BMS(电池管理系统)的HIL(硬件在环)仿真技术。首先阐述了整车建模的基础,包括电池、电机等关键部件的建模要点。接着分别解析了驾驶员模块、仪表模块、BCU整车控制器模块、MCU电机模块、TCU变速箱模块、BMS电池管理模块等多个子模块的功能和实现方式。最后强调了HIL仿真在电动汽车控制系统测试和优化中的重要性,特别是在降低成本和风险方面的作用。 适合人群:从事新能源汽车研发的技术人员,尤其是专注于VCU和BMS领域的工程师。 使用场景及目标:适用于需要深入了解电动汽车控制系统仿真技术的研发团队,在产品开发初期进行系统测试和优化,确保各子系统间的协同工作正常。 其他说明:文中提供了大量代码示例,帮助读者更好地理解和实践相关概念和技术细节。此外,还分享了一些实际项目中的经验和教训,如故障注入测试的具体应用场景等。

    如何应对一线人员春节后的离职潮.docx

    如何应对一线人员春节后的离职潮

    线性代数_GitHub_课件作业_教学辅助用途_1742837800.zip

    线性代数

    离职面谈表.xls

    离职面谈表.xls

    聚宽对接qmt大礼包,帮助你配置好交易实盘环境

    聚宽对接qmt大礼包,配备需要的全部软件:python3.9版本,qmt模拟安装包,pycharm安装包,talib包

    试用期转正表.xls

    试用期转正表.xls

    招聘数据分析.xls

    招聘数据分析.xls

    如何让新员工快速融入团队.docx

    如何让新员工快速融入团队

    电力电子仿真中并离网逆变器及无功补偿设备的控制策略与建模

    内容概要:本文详细介绍了并离网逆变器的两种主要控制策略——PQ控制和V/f控制,以及无功能量发生器(SVG)和有源电力滤波器(APF)的仿真模型。对于PQ控制,文章展示了如何将功率指令转化为电流指令,并强调了电网电压定向和限幅处理的重要性。V/f控制则用于离网模式,通过调节电压和频率来维持系统的稳定。SVG主要用于无功补偿,通过实时计算无功需求进行补偿。APF则专注于谐波检测和消除,利用自适应滤波器提高效率。此外,文中还提供了多个实用的小技巧,如仿真步长设置、模式切换时的前馈补偿等。 适合人群:从事电力电子仿真研究的技术人员,尤其是对逆变器控制策略感兴趣的工程师。 使用场景及目标:适用于需要深入理解和实现逆变器控制策略的研究项目,帮助工程师优化仿真模型,提升系统性能,确保仿真结果的准确性。 其他说明:文章不仅提供了详细的代码片段,还分享了许多实践经验,有助于读者避免常见错误,提高仿真成功率。

    Carsim与Simulink联合仿真中基于线性二自由度模型的卡尔曼滤波(KF)实现及优化

    内容概要:本文详细介绍了如何利用Carsim与Simulink进行联合仿真,通过线性二自由度模型和卡尔曼滤波(KF)来估计车辆的质心侧偏角和横摆角速度。首先搭建了联合仿真框架,Carsim提供车辆状态量,Simulink负责算法处理。文中展示了线性二自由度模型的状态方程及其参数设定,并深入探讨了KF的两种实现方式:S函数编程和Simulink内置模块。对于S函数实现,着重讲解了状态转移矩阵的动态更新以及噪声矩阵Q的调整策略,确保模型能够适应车速变化。而对于内置模块,则指出了其在灵活性方面的不足之处。此外,还讨论了联合仿真的配置要点,如数据接口同步、采样时间和信号处理等问题。 适合人群:从事车辆动力学研究、控制理论应用、自动化控制领域的工程师和技术人员。 使用场景及目标:适用于需要精确估计车辆质心侧偏角和横摆角速度的研究和开发项目,特别是在涉及ESP等主动安全系统的开发过程中。目标是提高估计精度,增强系统的鲁棒性和响应速度。 其他说明:文章提供了详细的代码片段和实践经验分享,帮助读者更好地理解和实施相关技术。建议在实际应用中根据具体需求选择合适的KF实现方式,并注意处理各种边界条件和异常情况。

    档案管理[03].pptx

    档案管理[03]

    风电与储能联合调频系统:基于Python的建模与优化

    内容概要:本文详细介绍了风电与储能联合调频系统的原理及其优化方法。首先解释了风电输出功率的波动性和对电网频率的影响,提出储能系统作为解决方案。文中展示了如何用Python生成风速数据并构建调频控制系统,重点讨论了PID控制器的设计以及SOC(荷电状态)管理策略。此外,还探讨了调频控制逻辑、硬件在环测试、风电功率预测模型(如LSTM)、调频效果验证方法及储能系统的物理限制等问题。最后强调了模型验证的重要性,提出了异常数据注入测试的方法。 适合人群:从事电力系统自动化、新能源发电及储能技术研发的专业人士,尤其是有一定编程基础的研究人员和技术工程师。 使用场景及目标:适用于需要理解和实施风电与储能联合调频项目的团队。主要目标是提高电网稳定性,减少风电波动带来的负面影响,同时延长储能系统的使用寿命。 其他说明:文中提供了大量实用的Python代码示例,涵盖了从数据生成到控制逻辑实现再到模型验证的全过程。对于希望深入理解风储调频系统的工作机制和技术挑战的人来说,是一份非常有价值的参考资料。

    HCIA-Storage V4.5 培训教材 合集

    HCIA-Storage V4.5 培训教材 合集

    基于S7-1200与博途V15的PLC小车自动往返控制系统设计与仿真

    内容概要:本文详细介绍了利用西门子S7-1200系列PLC和博途V15软件平台构建的小车自动往返控制系统。首先进行硬件组态,选择合适的CPU并配置输入输出点位,确保限位开关和急停按钮的有效接入。接着编写梯形图逻辑,实现小车在AB两点间的精确控制,采用定时器互锁机制避免电机损坏。然后设计触摸屏界面,通过WinCC创建动画效果展示小车运动状态,并设置按钮操作实现手动与自动模式切换。最后进行联合仿真实验,解决常见错误如变量地址配置不当等问题,确保系统稳定运行。 适合人群:工业自动化领域的工程师和技术人员,尤其是对PLC编程和HMI设计有一定基础的学习者。 使用场景及目标:适用于需要掌握PLC控制系统设计全流程的专业人士,帮助他们理解如何整合硬件组态、梯形图编程以及HMI开发,最终完成一个完整的自动化工程项目。 其他说明:文中提供了详细的调试经验和技巧,附带74分钟的操作录像资料,有助于读者更好地理解和实践相关知识点。

    公司员工关怀工作清单.xls

    公司员工关怀工作清单

    基于ANSYS/LS-DYNA的多孔延时起爆与重复起爆仿真技术详解

    内容概要:本文详细介绍了如何利用ANSYS/LS-DYNA进行多孔延时起爆和重复起爆的仿真。首先强调了起爆点的时间线控制和材料参数设置的重要性,如使用*INITIAL_DETONATION关键字设定起爆时间和坐标,以及配置JWL方程等材料属性。接着讨论了重复起爆的具体实现方式,包括使用*CONTROL_TERMINATION配合重启动功能,确保起爆点的正确复用。此外,文章还提供了调试技巧,如检查起爆同步性和优化时间步控制,以确保仿真的准确性。最后,分享了一些实际应用中的经验和常见错误,帮助用户更好地理解和掌握这一复杂的技术。 适合人群:从事爆炸力学研究和爆破工程设计的专业人士,尤其是有一定ANSYS/LS-DYNA使用经验的工程师。 使用场景及目标:适用于需要精确控制多个起爆点时间延迟和多次起爆的应用场合,如矿山开采、隧道挖掘等领域的爆破作业仿真。目标是提高爆破效率,减少对周围环境的影响。 其他说明:文中提到的许多技术细节对于初学者来说可能会有一定的难度,因此建议从简单的单孔起爆开始练习,逐步掌握复杂的多孔延时和重复起爆技术。同时,保持良好的注释习惯有助于追踪参数修改历史,便于后续调试和维护。

Global site tag (gtag.js) - Google Analytics