2009年9月 的存档

关于Java中serialization(序列化)

Object serialization的定义:

Object serialization 允许你将实现了Serializable接口的对象转换为字节序列,这些字节序列可以被完全存储以备以后重新生成原来的对象。 
serialization不但可以在本机做,而且可以经由网络操作(RMI)。这个好处是很大的—-因为它自动屏蔽了操作系统的差异,字节顺序(用Unix下的c开发过网络编程的人应该知道这个概念,我就容易在这上面犯错)等。比如,在Window平台生成一个对象并序列化之,然后通过网络传到一台Unix机器上,然后可以在这台Unix机器上正确地重构这个对象。

Object serialization主要用来支持2种主要的特性:

1。Java的RMI(remote method invocation).RMI允许象在本机上一样操作远程机器上的对象。当发送消息给远程对象时,就需要用到serializaiton机制来发送参数和接收返回直。
2。Java的JavaBeans.   Bean的状态信息通常是在设计时配置的。Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息。这也需要serializaiton机制。

二。关于持久化

英文中是persistence.但是Java语言里现在只支持lightweight persistence,就是轻量级持久化,这是通过serialization机制来实现的。
persistence是指一个对象的生命周期不由程序是否执行来决定,即使是在程序终止时这个对象也存在。它把一个serializable的对象写到磁盘(本机或其他机器上的非RAM存储器),并在程序重新调用时再读取对象到通常的RAM存储器。 举例而言,public class Student implements Serializable就是对这个Student 的javabean的持久应用序列化。
为什么说Java的serialization机制实现的是lightweight persistence?因为你必须显式的序列化和反序列化程序里的对象;而不是直接由一个关键词来定义一个对象是序列化的然后由系统做相应的处理。

Flex的事件流(转载)

本文载自:http://www.blogjava.net/usherlight/archive/2007/02/11/99340.html

Flex是一个事件驱动的编程模型, 任何事情的发生, 其背后必然存在一个事件. 而开发者第一次看到MXML时, 很难体会到一个Xml标记的应用的事件流和实例化的生命周期. 这个对于HTML和Flash的开发者尤其会感到困惑, 因为其熟悉的方式与Flex的一点也不相似. HTML的实例化是从上到下的, Flash的执行是从Frame0开始一帧帧运行的. 而Flex则又有不同.

从我们开始学习Flex时, 我们就需要了解事件流和MXML的实例化. 我非常困惑因为我实在难以理解什么样的事件会被触发或者事件什么时候会被触发. 关键是要理解事件的基础并亲自观察事件流的初始化.
我们来看一个简单的MXML的应用.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application
    xmlns:mx=”http://www.adobe.com/2006/mxml
    layout=”absolute”
    backgroundGradientColors=”[#67cbff, #fcffff]”
    color=”#000000″
    fontSize=”12″   
    preinitialize=”report( event , ‘preinitialize’ )”
    initialize=”report( event , ‘initialize’ )”
    creationComplete=”report( event , ‘creationComplete’ )”
    applicationComplete=”report( event , ‘applicationComplete’ )”
    >
   
    <mx:Script>
        <![CDATA[   
                   
            [Bindable]
           
            public var outTextData:String=”";
           
            public function report( event:Event , value:String ):void
            {
                outTextData += String( flash.utils.getTimer() ) + ‘ms >> ‘
                + event.currentTarget + ‘.’ + value + ‘\n’;   
            }
           
        ]]>
    </mx:Script>
   
    <mx:TextArea
        id=”outTextArea”
        text=”{ outTextData }”
        right=”10″ left=”10″ top=”50″ bottom=”10″ alpha=”0.5″
        wordWrap=”false”
        initialize=”report( event , ‘initialize’ )”
        creationComplete=”report( event , ‘creationComplete’ )”
        />
   
    <mx:Button
        y=”10″ height=”30″ left=”168″ width=”150″
        id=”HelloButton”
        label=”Say Hello”
        initialize=”report( event , ‘initialize’ )”
        creationComplete=”report( event , ‘creationComplete’ )”
        rollOver=”report( event , ‘rollOver’ )”
        rollOut=”report( event , ‘rollOut’ )”
        click=”report( event , ‘click > Hello!’ )”
        />
       
    <mx:Button
        id=”GoodByeButton”
        label=”Say Goodbye”
        y=”10″ left=”10″ height=”30″ width=”150″ color=”#000000″
        initialize=”report( event , ‘initialize’ )”
        creationComplete=”report( event , ‘creationComplete’ )”
        click=”report( event , ‘click > Goodbye!’ )”
        />
       
    <mx:Button
        id=”ClearButton”
        label=”Clear”
        y=”10″ left=”326″ height=”30″ color=”#000000″ right=”10″       
        initialize=”report( event , ‘initialize’ )”
        creationComplete=”report( event , ‘creationComplete’ )”
        click=”outTextData=”;report( event , ‘click’ )”
         />
   
</mx:Application>

这个应用运行时, 输出了实例流程和事件流. 这校我们就能够看到所有事件的触发顺序. 可以发现应用启动后, 事件的顺序是一定的. 下面是输出的内容:

167ms >> EventFlow0.preinitialize
183ms >> EventFlow0.outTextArea.initialize
187ms >> EventFlow0.HelloButton.initialize
188ms >> EventFlow0.GoodByeButton.initialize
189ms >> EventFlow0.ClearButton.initialize
189ms >> EventFlow0.initialize
243ms >> EventFlow0.outTextArea.creationComplete
243ms >> EventFlow0.HelloButton.creationComplete
243ms >> EventFlow0.GoodByeButton.creationComplete
244ms >> EventFlow0.ClearButton.creationComplete
244ms >> EventFlow0.creationComplete
246ms >> EventFlow0.applicationComplete

一旦applicationComplete事件触发后, 组件就会在鼠标事件派发后触发自己的事件.

1807ms >> EventFlow0.HelloButton.rollOver
2596ms >> EventFlow0.HelloButton.rollOut
2954ms >> EventFlow0.HelloButton.rollOver
3170ms >> EventFlow0.HelloButton.rollOut
3543ms >> EventFlow0.HelloButton.rollOver
4052ms >> EventFlow0.HelloButton.click > Hello!
4267ms >> EventFlow0.HelloButton.click > Hello!
4474ms >> EventFlow0.HelloButton.click > Hello!
4569ms >> EventFlow0.HelloButton.rollOut
4907ms >> EventFlow0.GoodByeButton.click > Goodbye!
5130ms >> EventFlow0.GoodByeButton.click > Goodbye!

运行实例:EventLifecycle

从一篇被懒人无注明转载的博文看Google和Baidu

废话少说,先看图,图一:
2009-09-21_091924

图二:

2009-09-21_092203
前些天在网上找东西,一不注意把自己以前写的一篇博客查了出来(如图一),想不到这样的小版权问题居然会出现在我身上,哈哈……不过转念一想,写这个文章的原意是帮助提供一个解决类似问题的方法,虽然是被无注明转载了,但是,另一层面而言,他也是在一定程度推动了这一知识的传播。嗯,所以也就不怪他了。

不过,接着我发现转载的博客是百度Hi,一时好奇,打开百度进行了同样条件的搜索,一看结果,真有点被雷到……那篇小有侵权的文章赫然排在第一位,而后搜不出我原来写的那篇……这时候真有点无语了,百度,作为民族的搜索引擎,注入了多少民族的希契,而它一直不争气。李彦宏老哥,虽然你最近抛出了弯道超车论,但这样的牛B谁不会吹?可以别在做这样的花哨功夫了吗?还记得08年你刚去北大演讲,说百度会专注于搜索,还引一实例为证,因为要坚持做搜索引擎,你一次次拒绝了手下提出的做电子商务的建议,在北大引起强烈反响。然而,在你演讲完没过多久,我看到百度有啊雷鸣上线,天大的讽刺!

敢把搜索技术提上来么,百度!敢不再只为了股东而上串下跳了么,百度!敢终有一天,让我重新使用百度搜索么!

Flex延迟加载

有时候我们在Flex开发中会遇到这样一种情况:有些组件在as中调用的时候run error:组件是null object or null method.这个时候使用延迟加载策略能够很好的解决问题,如:

internal function eventHandler():void{
  if(paginationComp==null)
  //表示若此组件还未初始化,则等待10ms,一直到组件初始化完毕
    setTimeout(eventHandler,10); 
}

如果function是带参数的,是如下用法:

internal function eventHandler(evt:Event):void{
  if(paginationComp==null)
  //表示若此组件还未初始化,则等待10ms,一直到组件初始化完毕
    setTimeout(eventHandler,10,evt); 
}

Part 2:

经常的,一些null object or method的Error可以藉由creationComplete(callLater(init))来处理,表示在组件初始化完毕的下一帧才执行init()这个function

Flexlib—-Advanced Flex UI Componets

flexlib_logo

 不详细介绍了,感兴趣的自己看一下:

Flex lib Home Page & Download:http://code.google.com/p/flexlib/

Flex lib Discussion Group:http://groups.google.com/group/flexlib

Online Demo(Also call componet list~):http://code.google.com/p/flexlib/wiki/ComponentList

RSL--Flex swf 御用减肥专家

RSL ( Runtime Shared Library )——运行时组件共享库,用就是使同域里的项目可共享资源,这样可以节省项目的档案大小,易切割、易搬运、易分享组件库项目与组件库可分开开发 .如下图:
Flex-RSL
下面用图文的方式展示在Flex Builder中使用RSL给Project减肥的步骤。首先来看看减肥之前的”体重”:2009-09-07_153250

如上图所示:bookForm.swf 大小为461KB,EPortal.swf大小为482KB,接着来到Flex Buidler,在工程上点右键,选Properties,接着来到Flex Build Path面板中,看Library Path,在Framework linkage后选择使用Runtime Shared Library(RSL).这时候给Flex lib加入RSL,然后在Build Path Libraries中能看到framework.swc中出现RSL URL:framework_3.2.0.3958.swz(注:本人使用的Flex SDK版本为3.2.0.3958),选中后进行编辑查看,流程如下图所标示:
2009-09-07_153933

打开后,确认Deployment path中是否已有这两项:framework_3.2.0.3958.swz,framework_3.2.0.3958.swf。如果没有的话点add按钮添加进去。然后,一路OK,OK到最后。

2009-09-07_154616

OK都点完了,Flex Builder会进行编译工作,等它编译完了,就可以来到文件夹查看效果了:

2009-09-07_155240呵呵,明显的,bookForm.swf和EPortal.swf已经产生了质的飞越~不过同时应该注意,RSL虽然能给swf减肥,但同时也给工程载入了两个文件:framework_3.2.0.3958.swz,framework_3.2.0.3958.swf。我们在实际应用中,应该考量比较应用RSL前后的大小状况,然后再选择是否使用RSL.

此外,RSL同时支持字型定义共享库,应用中对共享应用的部分您自行归纳整理一些常用的数据、函式、类别、接口…等。

Flex CSS 样式编辑器 Flex3StyleExplorer

一直手动写Flex CSS,今天突然从老资料堆里翻出来这个东西,可以自助生成CSS样式表

这东西,遇到搞不定的样式的时候,翻出来用用还是不错滴~

Flex CSS Style Editor 样式编辑器 Flex3StyleExplorer.swf (559)

对噢,顺便附上源码:Flex3StyleExplorer.zip (225)

最简单易理解的Flex PureMVC入门例子:实现登录

2010/1/14日更新
加入官方一个Demo:Demo_AS3_Flex_CafeTownsend.zip (188)

_____________________________华丽的分割线________________________________

PureMVC 学习笔记(一)中介绍了一个《flex框架pureMVC的使用:第一步》(后简称:第一步)的例子,此文关于PureMVC的介绍非常生动明了,如果想快速学习PureMVC这个framework的话,建议看一下。

不过其中所举例子对于想要自己动手使用PureMVC的人就稍显不足了。因为《第一步》对于代码的介绍是从application启动加载Facade开始的,然后注册Command,Proxy,Mediator,这样的说明的好处是快速让读者理解PureMVC内部运行机制。在理解了PureMVC的原理之后,我们就要开始构思怎样对一个工程应用PureMVC,谨以一个登录的例子,说明如何使用PureMVC构建工程,工程结构图如下:

2009-09-04_112259

因为所有的 Mediator、Proxy、Command、Event 的名称都被我定义在system包下的NameSpace.as中,所以先看给出此as的代码:

package system
{

 public class NameSpace
 {
  public static const LoginProxyName:String=”LoginProxy”;
  public static const LoginSuccess:String=”loginSuccess”;
  public static const LoginFailed:String=”loginFailed”;
  public static const LoginEvent:String=”loginEvent”;
  public static const LoginMediatorName:String=”loginMediator”;
  public static const ApplicationLogin:String=”login”;
  public static const ApplicationMediatorName:String=”appliactionMediator”;
  public static const FacadeStart:String=”start”;
 }
}

Model和Proxy

因为数据来自Model层,我们用Proxy进行管理,所以我们先来设计这一模块,定义LoginVO这样一个简单的数据结构,用于存储登录的数据:用户名和密码。代码如下:

package model.vo
{
 public class LoginVO
 {
  public var username:String;
  public var password:String;
 }
}

 接着建立LoginProxy,需要继承Proxy实现IProxy:

package model
{
 import model.vo.LoginVO;
 import org.puremvc.as3.interfaces.IProxy;
 import org.puremvc.as3.patterns.proxy.Proxy;
 import system.NameSpace;

 public class LoginProxy extends Proxy implements IProxy
 {
  public function LoginProxy()
  {
   super(NameSpace.LoginProxyName);
  }

  public function CheckLogin(vo:LoginVO):void
  {
   if (vo.username == “test” && vo.password == “test”)
   {
    sendNotification(NameSpace.LoginSuccess, vo);
   }
   else
   {
    sendNotification(NameSpace.LoginFailed);
   }
  }
 }
}

每一个Proxy都需要有自己的名称,为了便于统一的管理,我把所有的Name都定义在NameSpace中,这样做的好处是有利于协作开发,同时也有助于程式的调试。从代码中可以看到,整个Model与外界没什么联系,提供了一个CheckLogin()方法,根据判断的结果发送通知。至于这样的通知发送出去谁来处理,怎么处理,就不是Proxy关心的事了。由此可知,Proxy的耦合度相当低!(感觉PureMVC这个组织里,Facade是老大,管着手下三个小弟:Proxy、Mediator、Command,这三个家伙都是各干各的,从不互相帮助,各人自扫门前雪,真是selfish)

View 和 Mediator

任何一个应用都有和用户交互的界面,将这些界面统一起来进行管理,就是PureMVC的View层。在View层内,实现界面的管理委托给了Mediator,Mediator负责管理应用界面的数据更新和提交数据。当用户界面发生数据更新或用户操作时,界面通过事件通知管理它的Mediator,然后Mediator会根据情况发送通知给系统。先建议一个登录的界面:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Panel xmlns:mx=”http://www.adobe.com/2006/mxml
    fontSize=”12″
    layout=”vertical”
    horizontalAlign=”center”
    title=”用户登录”
    width=”314″>
 <mx:Script>
  <![CDATA[
   import system.NameSpace;
  ]]>
 </mx:Script>
 <mx:Form width=”100%”
    height=”100%”>
  <mx:FormHeading label=”敬请登录”/>
  <mx:FormItem label=”登录名称”>
   <mx:TextInput id=”loginName”/>
  </mx:FormItem>
  <mx:FormItem label=”登录密码”>
   <mx:TextInput id=”loginPassword”/>
  </mx:FormItem>
  <mx:FormItem>
   <mx:Button label=”确定”
        id=”loginBtn”
        click=”dispatchEvent(new Event(NameSpace.LoginEvent))”/>
  </mx:FormItem>
 </mx:Form>
 <mx:Label id=”labStatus”/>
</mx:Panel>

基于这个界面,定义两个Mediator:一个是LoginMediator,负责管理登录对话框和登录的操作;另一个是ApplicationMediator,用来负责管理登录成功后的界面。先看LoginMediator:

package view
{
 import flash.events.Event;

 import model.vo.LoginVO;

 import mx.managers.PopUpManager;

 import org.puremvc.as3.interfaces.IMediator;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.mediator.Mediator;

 import system.NameSpace;

 public class LoginMediator extends Mediator implements IMediator
 {
  //获取应用实例
  private var loginPanel:LoginForm;
  private var loginApplication:PureLoginMVC;

  public function LoginMediator(app:Object)
  {
   super(NameSpace.LoginMediatorName, app);
   loginApplication=app as PureLoginMVC;
   loginPanel=new LoginForm();
   loginPanel.addEventListener(NameSpace.LoginEvent, onLogin);
   PopUpManager.addPopUp(loginPanel, loginApplication);
   PopUpManager.centerPopUp(loginPanel);
  }

  //监听通知
  override public function listNotificationInterests():Array
  {
   var arr:Array=new Array();
   arr.push(NameSpace.LoginSuccess);
   arr.push(NameSpace.LoginFailed);
   return arr;
  }

  //响应通知
  override public function handleNotification(notification:INotification):void
  {
   switch (notification.getName())
   {
    case NameSpace.LoginSuccess:
     setLoginSuc();
     break;
    case NameSpace.LoginFailed:
     setLoginFailed();
     break;
    default:
     break;
   }
  }

  //登录成功,移除登录窗口
  private function setLoginSuc():void
  {
   PopUpManager.removePopUp(loginPanel);
  }

  //登录失败,提示
  private function setLoginFailed():void
  {
   loginPanel.labStatus.text=”用户名密码有误,请重试”;
   loginPanel.loginName.setFocus();
  }

  private function onLogin(evt:Event):void
  {
   if (loginPanel.loginName.text != “” && loginPanel.loginPassword.text != “”)
   {
    var loginVO:LoginVO=new LoginVO();
    loginVO.username=loginPanel.loginName.text;
    loginVO.password=loginPanel.loginPassword.text;
    sendNotification(NameSpace.ApplicationLogin, loginVO);
   }
   else
   {
    loginPanel.labStatus.text=”请输入用户名和密码”;
   }
  }

 }
}

同样,LoginMediator 的名称来自于 NameSpace.as ,继承Mediator实现IMediator,LoginMediator 注册监听了两个事件:登录成功和失败,并做了对应的响应处理。其中onLogin()方法在收集了登录信息后,发出通知。另外还有一个ApplicationMediator:

package view
{
 import model.vo.LoginVO;

 import mx.controls.Label;

 import org.puremvc.as3.interfaces.IMediator;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.mediator.Mediator;

 import system.NameSpace;

 public class ApplicationMediator extends Mediator implements IMediator
 {
  private var loginApplication:PureLoginMVC;

  //构造器,获取application实例
  public function ApplicationMediator(app:Object)
  {
   super(NameSpace.ApplicationMediatorName, app);
   loginApplication=app as PureLoginMVC;
  }

  //监听通知
  override public function listNotificationInterests():Array
  {
   return [NameSpace.LoginSuccess];
  }

  //响应通知
  override public function handleNotification(notification:INotification):void
  {
   switch (notification.getName())
   {
    case NameSpace.LoginSuccess:
     setLoginSuc(notification.getBody() as LoginVO);
     break;
    default:
     break;
   }
  }

  private function setLoginSuc(loginVO:LoginVO):void
  {
   var label:Label=new Label();
   label.text=”欢迎光临!” + loginVO.username;
   loginApplication.addChild(label);
  }

 }
}

这个mediator只监听了登录成功的通知,并响应更新主应用上的数据。

Controller 和 Command

Controller和Command看起来像一条纽带,联系这Mediator和Proxy.它处理Mediator发送的通知并调用Proxy中的public 方法来处理. Command需要继承SimpleCommand或MocroCommand并实现ICommand.分析系统,需要在Command中注册Proxy和Mediator,以及一个处理Login的。这里的设计思路为:ModelCommand(用于注册Proxy)、ViewCommand(注册Mediator)、ApplicationCommand(用于系统启动时,集成ModelCommand和ViewCommand)、LoginCommand(用于接收登录通知并调用Proxy实现登录)。先看ModelCommand:

package Controller
{
 import model.LoginProxy;

 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 public class ModelCommand extends SimpleCommand implements ICommand
 {
  public function ModelCommand()
  {
   super();
  }

  override public function execute(notification:INotification):void
  {
   facade.registerProxy(new LoginProxy());
  }

 }
}

接着写ViewCommand:

package Controller
{
 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 import view.ApplicationMediator;
 import view.LoginMediator;

 public class ViewCommand extends SimpleCommand implements ICommand
 {
  public function ViewCommand()
  {
   super();
  }

  //注册Mediator
  override public function execute(notification:INotification):void
  {
   var app:PureLoginMVC=notification.getBody() as PureLoginMVC;
   facade.registerMediator(new ApplicationMediator(app));
   facade.registerMediator(new LoginMediator(app));
  }

 }
}

在ApplicationCommand中集成注册上面两个Command:

package Controller
{
 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.patterns.command.MacroCommand;

 public class ApplicationCommand extends MacroCommand implements ICommand
 {
  //构造器,可写可不写
  public function ApplicationCommand()
  {
   super();
  }

  //写法一
  override protected function initializeMacroCommand():void
  {
   addSubCommand(ModelCommand);
   addSubCommand(ViewCommand);
  }

 }
}

处理登录通知的LoginCommand:

package Controller
{
 import model.LoginProxy;
 import model.vo.LoginVO;

 import org.puremvc.as3.interfaces.ICommand;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.command.SimpleCommand;

 import system.NameSpace;

 public class LoginCommand extends SimpleCommand implements ICommand
 {
  public function LoginCommand()
  {
   super();
  }

  override public function execute(notification:INotification):void
  {
   var loginVO:LoginVO=notification.getBody() as LoginVO;
   //var loginProxy:LoginProxy = new LoginProxy();
   //从facade中获取proxy
   var loginProxy:LoginProxy=facade.retrieveProxy(NameSpace.LoginProxyName) as LoginProxy;
   loginProxy.CheckLogin(loginVO);
  }

 }
}

完成了这些之后,就到了 PureMVC 的核心:Facade,通过它,Mediator,Proxy,Command才能很好的结合在一起。这里将它命名为MyFacade,代码如下:

package view
{
 import model.vo.LoginVO;

 import mx.controls.Label;

 import org.puremvc.as3.interfaces.IMediator;
 import org.puremvc.as3.interfaces.INotification;
 import org.puremvc.as3.patterns.mediator.Mediator;

 import system.NameSpace;

 public class ApplicationMediator extends Mediator implements IMediator
 {
  private var loginApplication:PureLoginMVC;

  //构造器,获取application实例
  public function ApplicationMediator(app:Object)
  {
   super(NameSpace.ApplicationMediatorName, app);
   loginApplication=app as PureLoginMVC;
  }

  //监听通知
  override public function listNotificationInterests():Array
  {
   return [NameSpace.LoginSuccess];
  }

  //响应通知
  override public function handleNotification(notification:INotification):void
  {
   switch (notification.getName())
   {
    case NameSpace.LoginSuccess:
     setLoginSuc(notification.getBody() as LoginVO);
     break;
    default:
     break;
   }
  }

  private function setLoginSuc(loginVO:LoginVO):void
  {
   var label:Label=new Label();
   label.text=”欢迎光临!” + loginVO.username;
   loginApplication.addChild(label);
  }

 }
}

 最后,在主应用中单例调用MyFacade的实例:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application fontSize=”12″
    xmlns:mx=”http://www.adobe.com/2006/mxml
    creationComplete=”init()”
    layout=”absolute”>
 <mx:Script>
  <![CDATA[
   import system.MyFacade;
   import org.puremvc.as3.patterns.facade.Facade;

   public function init():void
   {
    var myFacade:MyFacade=MyFacade.getInstance();
    myFacade.startup(this);
   }
  ]]>
 </mx:Script>
</mx:Application>

到此为止,一个PureMVC构建的登录例子就完成了,呵呵,希望能达到一看就懂的效果~

源码下载:PureMVCLogin.rar (679)

Flex PureMVC使用时的注意事项(转载)

PureMVC大大的优化了我们使用FLEX进行前台的开发,使得整个开发过程变的较为可控,但是如果放任程序员去自由的使用pureMVC也会带来很大的隐患。本文内容主要记录我使用pureMVC开发原型这一个星期来使用的一些开发规范和经验总结。

1. 如果有个项目有几个开发人员共同开发,同时采用版本控制工具对项目项目的源码进行版本控制,可是维护通

知的名称着实让人烦恼,我们若要将通知名称放在同一 个类中{ApplicationFacade}就不能很好的使用版本控制工具,因为每个人都要修改这个类 {在你修改时你要看看别人是否已经修改该文件,别人若是修改了还得让他提交,然后自己更新再修改,太痛苦了!} ,而且都放在一个类里也会增加维护的难度,那么有没有什么好的办法呢?

通常一两个人做个例子时遇到这种情况可能比较好解决,单如果参与的人较多的化,可能花在协调上面的工作

量就会比较多,为了增加开发的速度,使开发变的更加的简单,我们可以让通知名称分散到各个模块的Mediator

类中进行维护{每个模块主页面的协调类,可根据自己的系统大小控制粒度},这样每个开发人员可以只要维护自身的通知名称或者只要与一两个人进行协调,同时我们要求每个通知名称都要包含该类所在的包路径和类名称,具体的格式可以是“通知名称+包路径.类名称”,这样我们只要保证通知名称唯一,且便于日后维护。

2. 每个Mediator,Proxy都要定一个NAME属性,通常我要求每个NAME属性必须是“包路径+类名称”,也是

为了避免不必要的冲突,找半天BUG。

3. PureMVC中Mediator似乎什么都可以坐了,Command的用处似乎不大。

这是一个错误的看法,虽然我们在Mediator中可以直接获取到Proxy,Mediator类的对象,也可以注册

Mediator,Proxy,Command,但是我们必须给自已一个约束,不然随着开发的不断深入你会发现代码也越来越乱。所以我们增加了较为严禁的约束:

3.1 通常情况在程序启动后,Mediator负责注册Command,以及派发通知和接收通知,当Mediator类需要进行当前范围外的一些操作时就可以通过派发通知的方式。一般来说页面UI主要负责页面的布局和简单的作,其他的应该交由Mediator来处理。例如,Mediator协调的UI需要获取数据,这是Mediator可以派发一个获取数据的通知(之前已经注册一个用于处理该通知的Command),然后有pureMVC会初始化被注册的Command并执行获取数据的操作。如果你需要告知另外一个页面进行某些操作或者增加一个新的页面,也应该通过派发通知的方式来处理,应避免在当前Mediator类中直接获取响应页面的对象或者获取Mediator类进行操作,如果是增加一个新的页面应当在页面加载后将该页面的对象作为报体通知Command进行注册以及其他操作。

3.2 Command主要负责注册Mediator和Proxy以及协调Mediator和Proxy之间的操作,应当将复杂的操作放在这里处理。Command的注册不必集中但也不可以太过分散,一般来说放在比功能级稍大点的Mediator中来注册(例如一个增删改查,4个页面需要不停的切换,关于这4个页面功能的Command一般来说都是放在这四个页面的上一层页面的Mediator中进行注册,也就是管理这四个页面的Mediator中)。当我们要增加啊一个新的UI时需要通知Command来注册Mediator,需要调用model层对数据进行处理时也应通知Command来调用,如果一个Command类里的代码过多,应当考虑进行拆分,Command类应尽可能分的细点,便于维护。

3.3Proxy主要负责对数据的维护以及与服务器端进行通信处理数据。Proxy应当做到只做纯粹的数据处理不干涉过多的逻辑处理,不关心外面发生了什么事情,只要在数据处理后派发通知来通知外界即可,如果各个Proxy之间需要进行交互,那也应该在Command中来是先调用不用Proxy的方法,不要在Proxy中直接去调用另一个Proxy更不能去调用Mediator。

4.注意清除你不用的Mediator,Proxy,Command应当及时的清除,pureMVC采用观察者模式,及时的清楚能减轻系统的负担,但是有时无法做到清楚指定的Mediator等对象,所以在每次注册新的Mediator,Command,Proxy时要判断是否已经存在相同的类,然后根据自己的需要选择是重新注册还是继续使用以前的,切不可同时注册两个相同的,例如:当你有两个相同的Mediator时,你通过NAME属性去获取该对象,那究竟获取哪一个对象才是你想要的呢?

一款能将Flash Catalyst和Flash Builder 4项目同步的AIR应用

用Flash Catalyst设计完后,许多开发者会遇到导入到Flash Builder 4 不好处理的问题,如今可以尝试使用:CatalystBuilderSync

CatalystBuilerSync
CatalystBuilerSync

 

基于AIR,英文界面,简单易用