1.项目简介
??? 本人准备开发一个信息管理系统,经过详细的考虑,决定采用基于parsley的MVC框架作为FLEX开发的框架。
??? parsley的MVC框架的优点
??????? .适当解耦(视图类和视图model类、控制类与service类),提高了程序的可读性和可维护性
??????? .避免使用FLEX的事件传播机制,降低了系统运行的风险(过多的注册监听事件会带来意想不到的问题,比如不及时删除无用的事件监听器,会阻止垃圾回收器从而造成内存泄露,而且它们还很难跟踪并且影响程序的性能)
??????? .适当的对象托管会给编程带来方便
??? 下图所示:
??? parsley的MVC框架中,一个典型的模块的包分为六个部分:视图包、视图model包、Command包、Model包、Service包、消息包。
??? 类与类之间的数据传递通过框架提供的消息来完成。
??? 由于消息类大量的与Model类重复,比如创建用户消息类CreateUserMessage中只有一个类User.从整体上看提高了程序可读性,但是加大了编码工作量,本人决定舍弃消息层,将消息包与Model包合并成Model层,比如CreateUserCommand类的参数直接使用UserModel,而不是CreateUserMessage。
部分代码说明如下:
??? <spicefactory:DynamicCommand type="{CreateUserCommand}" messageType="{CreateUserMessage}" />
取消了Message包后,
??? <spicefactory:DynamicCommand type="{CreateUserCommand}" messageType="{UserModel}" />
2.项目目录结构
src
?? --默认包
?????? --index.mxml?? //首页面
?????? --Config.mxml? //根配置文件
?? --com.teacherHome
?????? --system
????????? --config
????????????? --SystemConfig.mxml? //系统管理模块配置文件
????????? --commands
????????????? --CreateXsCommand.as??? //创建学生命令
????????????? --DeleteBjCommand.as??? //删除班级命令
????????? --models
????????????? --LoginModel.as???????? //登录数据类
????????????? --XsModel.as??????????? //学生数据类
????????????? --BjModel.as??????????? //班级数据类
????????? --Services
????????????? --XsSevice.as?????????? //学生远程服务类
????????????? --BjService.as????????? //班级远程服务类
????????????? --mock
?????????????????? --XsServiceMock.as //学生服务测试类
?????????????????? --BjServiceMock.as //班级服务测试类
????????? --view
????????????? --components
?????????????????? --CjPanel.mxml???? //成绩组件
????????????? --renderers
?????????????????? --ImageRenderer.mxml //Render组件
????????????? --skins
?????????????????? --CjListSkin.mxml? //成绩列表皮肤组件
????????????? SystemMain.mxml???????? //系统管理主页面
????????? --styles
????????????? --System.css??????????? //系统管理的CSS文件
3.视图包与视图model包
??? 视图类负责组织页面的组件显示,只包含组件和组件事件处理函数。视图model类注入到视图中,负责管理业务逻辑。
例:
登录视图类代码片段:
??? <mx:Script>
??? ??? <![CDATA[
??? ??? ??? import com.adobe.system.view.LoginPM;
??? ??? ????
??? ??? ??? [Bindable]
??? ??? ??? [Inject]
??? ??? ????public var pm : LoginPM;//视图model类
??? ??? ????
??? ??? ??? private function handleKeyDown( event : KeyboardEvent ) : void
??? ??? ??? {
??? ??? ??? ??? if( event.keyCode == Keyboard.ENTER )
??? ??? ??? ??? {
??? ??? ??? ??? ??? pm.username=usernameInput.text;
??? ??? ??? ??? ??? pm.password=passwordInput.text;
??? ??? ??? ??? ????
??? ??? ??? ??? ??? pm.login(username, password);
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? protected function button1_clickHandler(event:MouseEvent):void
??? ??? ??? {
??? ??? ??? ????pm.login(username, password);? //业务逻辑也封装在视图model中
??? ??? ??? }
??? ??? ]]>
??? </mx:Script>
????
??? <mx:Panel horizontalCenter="0"
??? ??? ??? ? verticalCenter="0">
??? ??? <mx:Form
??? ??? ??? keyDown="handleKeyDown( event )">
??? ??? ??? <mx:FormItem label="name">
??? ??? ??? ??? <mx:TextInput?
??? ??? ??? ??? ??? id="usernameInput"
??? ??? ??? ??? ??? text="{?pm.username?}"/>? //数据封装在视图model类中
??? ??? ??? </mx:FormItem>
??? ??? ??? <mx:FormItem label="password">
??? ??? ??? ??? <mx:TextInput?
??? ??? ??? ??? ??? id="passwordInput"?
??? ??? ??? ??? ??? text="{?pm.password?}"
??? ??? ??? ??? ??? displayAsPassword="true"/>
??? ??? ??? </mx:FormItem>
??? ??? </mx:Form>
??? ????
??? ??? <mx:CheckBox
??? ??? ??? label="Model injected?"
??? ??? ??? labelPlacement="left"
??? ??? ??? enabled="false"
??? ??? ??? selected="{ pm != null }"/>
??? ????
??? ??? <mx:Button?
??? ??? ??? label="login"
??? ??? ??? ?click="button1_clickHandler(event)"/>
??? </mx:Panel>
视图model类
??? public class LoginPM?
??? {
??? ??? public var username : String="good";
??? ??? public var password : String="bad";
??? ??? public var isinit:Boolean=false;
??? ????
??? ??? [init]
??? ??? public function LoginPM():void
??? ??? {
??? ??? ??? isinit=true;
??? ??? }
??? ????
??? ????[MessageDispatcher]
??? ??? public var sendMessage:Function;
??? ????
??? ??? public function setUsername( username : String ) : void
??? ??? {
??? ??? ??? this.username = username;
??? ??? }
??? ????
??? ??? public function setPassword( password : String ) : void
??? ??? {
??? ??? ??? this.password = password;
??? ??? }
??? ????
??? ??? public function login( username:String, password:String ):void {
??? ??? ????
??? ??? ??? if( username != '' && password != '' ) {
??? ??? ??? ??? message = '';
??? ??? ??? ??? var loginMessage:LoginMessage = new LoginMessage( username, password );
??? ??? ??? ????sendMessage( loginMessage );? //派发消息
??? ??? ??? }
??? ??? }
??????? //接收登录处理结果,当Commandod类的方法result处理完成后,自动派发CommandResult命令
??????? [CommandResult(type="com.messages.LoginMessage")]
??? ??? public function handleResult() : void {
??? ??? ??? if( session.loggedIn ) {
??? ??? ??? ??? mainPresentationModel.switchTo( Constants.STATE_DASHBOARD );
??? ??? ??? }
??? ??? ??? else {
??? ??? ??? ??? message = ResourceManager.getInstance().getString(
??? ??? ??? ??? ??? 'General', 'loginFailed' );
??? ??? ??? }
??? ??? }
??????? //当Commandod类的方法error处理完成后,自动派发CommandError命令
??? ??? [CommandError(type="com.messages.LoginMessage")]
??? ??? public function handleError():void {
??? ??? ??? message = ResourceManager.getInstance().getString(
??? ??? ??? ??? 'General', 'serviceFailed' );
??? ??? }
??? }
4.Command包
??? 一个服务对应着一个Command类,比如CreateUserCommand,LoadUsersCommand。
例子代码:
public class LoginCommand {
??? ??? [Inject]
??? ??? public var loginService:IUserService;
??? ????
??? ??? [Inject]
??? ??? public var session:Session;
??? ????
??? ??? private static const logger:Logger = LogContext.getLogger( LoginCommand );
??? ????
??? ??? public function execute( message:LoginMessage ):AsyncToken {
??? ??? ??? return loginService.login( message.username, message.password );
??? ??? }
??? ????
??? ??? public function result ( user:User ) : void {
??? ??? ??? if( user != null ) {
??? ??? ??? ??? session.loggedIn = true;
??? ??? ??? ??? session.user = user;
??? ??? ??? }
??? ??? ??? else {
??? ??? ??? ??? session.loggedIn = false
??? ??? ??? }
??? ??? }
??? ????
??? ??? public function error (fault:Fault) : void {
??? ??? ??? logger.error( "service call failed: " + fault.message );
??? ??? }
??? ????
??? ????
??? }
在配置文件中必须设置动态命令标签:
??? <spicefactory:DynamicCommand type="{LoginCommand}" />
5.Service包
??? Service类负责与后台进行交互,从WEB服务器或数据库获取数据。
模拟后台调用代码如下:
??? public class UserService implements IUserService {
??? ??? private var user:User;
??? ??? private var mockServiceUtil:MockServiceUtil = new MockServiceUtil;
??? ????
??? ??? public function LoginServiceMock() {
??? ??? ??? user = new User();
??? ??? ??? user.id = "1";
??? ??? ??? user.firstname = "Jochen";
??? ??? ??? user.lastname = "Hilgers";
??? ??? }
??? ????
??? ??? public function login(username:String, password:String):AsyncToken {
??? ??? ??? return mockServiceUtil.createToken( user );
??? ??? }
6.Model包
??? model类负责封装对象的属性,model类主要分为二种:一、实体对象,比如用户UserModel,班级BjModel等;二、传递的消息,比如登录事件中传递的LoginMessage。
例子:
??? public class LoginMessage {
??? ??? public var username:String;
??? ??? public var password:String;
??? ????
??? ??? public function LoginMessage( username:String, password:String ) {
??? ??? ??? this.username = username;
??? ??? ??? this.password = password;
??? ??? }
??? }
??? [RemoteClass(alias="com.model.User")]
??? public class User {
??? ????
??? ??? public var id:String;
??? ??? public var firstname:String;
??? ??? public var lastname:String;
??? }
转自:http://blog.chinaunix.net/space.php?uid=122937&do=blog&id=143083