AS3 PureMVC之核心层

来源:互联网 发布:服装品牌知乎 编辑:程序博客网 时间:2024/06/05 05:01
原文:http://uh.9ria.com/space-44647-do-blog-id-4823.html

下载PureMVC的源代码并导入到FB4后,我们可以看到org.puremvc.as3这个包,其中有个core包,这里面的就是PureMVC的核心包。
我们可以看到核心包里面有三个类:Model, View, Controller。这是经典MVC元设计模式中的三个类。我们查看一下这三个类的原代码,可以发现这三个类都是单例模式类。
这些稍稍提下这三个类的单例实现方法,如Model类
public function Model( )
  {
   if (instance != null) throw Error(SINGLETON_MSG);
   instance = this;
   proxyMap = new Array(); 
   initializeModel(); 
  }
 
/**
   * <code>Model</code> Singleton Factory method.
   * 
   * @return the Singleton instance
   */
  public static function getInstance() : IModel 
  {
   if (instance == null) instance = new Model( );
   return instance;
  }
我们可以看到在构造函数中if (instance != null) throw Error(SINGLETON_MSG);如果实例为空,则抛出一个异常,这样我们就无法通过构造函数来实例化这个类,而必须通过getInstance()方法来创建并返回一个实例。呵呵,这个实现比较有意思。之前了解的单例的实现方法是能过在as文本中的包外声明一个类,将这个类对象做为需要单例的类的构造函数的参数,这样阻止了外部通过构造函数来实例化这个类了。
 
下面我们一个类一个类来分析下源代码吧
 
Model
Model类用于保存对Proxy对象的引用,并通过Proxy来操作数据模型,与远程服务通信存取数据。Model类实现了IModel接口。IModel接口声明了如下四个方法,这些方法主要是通过名称来操作Proxy实例对象(除registerProxy):
  • function registerProxy( proxy:IProxy ) : void;              //用于注册Proxy实例
  • function retrieveProxy( proxyName:String ) : IProxy;   //用于获取名为proxyName的Proxy实例
  • function removeProxy( proxyName:String ) : IProxy;   //移除名为proxyName的Proxy实例
  • function hasProxy( proxyName:String ) : Boolean;       //判断是否有名为proxyName的Proxy实例
Model类中有一个proxyMap数组,这个数组通过关联数组的方式来存储Proxy实例,在实现IModel接口的方法中,通过处理这个数组来管理Proxy实例对象,如下
/**
   * Register an <code>IProxy</code> with the <code>Model</code>.
   * 
   * @param proxy an <code>IProxy</code> to be held by the <code>Model</code>.
   */
  public function registerProxy( proxy:IProxy ) : void
  {
   proxyMap[ proxy.getProxyName() ] = proxy;
   proxy.onRegister();
  }
View
View保存了对Mediator对象的引用,并通过Mediator对象来操作具体的视图组件(这些操作包括添加事件监听器、发送或接收Notification、直接改变视图组件的状态)。View类实现了IView接口,IView接口声明了如下方法:
  • function registerMediator( mediator:IMediator ) : void;          //注册Mediator对象
  • function retrieveMediator( mediatorName:String ) : IMediator;//获取Mediator对象
  • function removeMediator( mediatorName:String ) : IMediator;//移除Mediator对象
  • function hasMediator( mediatorName:String ) : Boolean;        //决断是否有Mediator对象
  • function registerObserver( notificationName:String, observer:IObserver ) : void;//注册一个Observer对象
  • function removeObserver( notificationName:String, notifyContext:Object ):void;//移除一个Observer对象
  • function notifyObservers( note:INotification ) : void;             //通知Observer对象
从这些方法中我们可以看出View的主要任务应该是分成两部分:管理Mediator和处理消息。因此,View中有保存了两个数组:mediatorMap(保存Madiator名与Mediator对象的映射)和observerMap(保存Observer名与Observer对象列表的映射:注意,这是列表),当然因为Observer列表是与Mediator相关的,所以在处理Mediator对象时,也相应滴处理了相关的Observer列表,如下:
/**
   * Register an <code>IMediator</code> instance with the <code>View</code>.
   * 
   * <P>
   * Registers the <code>IMediator</code> so that it can be retrieved by name,
   * and further interrogates the <code>IMediator</code> for its 
   * <code>INotification</code> interests.</P>
   * <P>
   * If the <code>IMediator</code> returns any <code>INotification</code> 
   * names to be notified about, an <code>Observer</code> is created encapsulating 
   * the <code>IMediator</code> instance's <code>handleNotification</code> method 
   * and registering it as an <code>Observer</code> for all <code>INotifications</code> the 
   * <code>IMediator</code> is interested in.</p>
   * 
   * @param mediatorName the name to associate with this <code>IMediator</code> instance
   * @param mediator a reference to the <code>IMediator</code> instance
   */
  public function registerMediator( mediator:IMediator ) : void
  {
   // Register the Mediator for retrieval by name
   mediatorMap[ mediator.getMediatorName() ] = mediator;
   
   // Get Notification interests, if any.
   var interests:Array = mediator.listNotificationInterests();
   // Register Mediator as an observer for each of its notification interests
   if ( interests.length > 0 ) 
   {
    // Create Observer referencing this mediator's handlNotification method
    var observer:Observer = new Observer( mediator.handleNotification, mediator );
    // Register Mediator as Observer for its list of Notification interests
    for ( var i:Number=0;  i<interests.length; i++ ) {
     registerObserver( interests[i],  observer );
    }   
   }
   
   // alert the mediator that it has been registered
   mediator.onRegister();
   
  }
Controller
Controller保存所有的Command的映射。
Controller类实现了IController接口。该接口声明了如下方法:
  • function registerCommand( notificationName : String, commandClassRef : Class ) : void; //注册Command
  • function executeCommand( notification : INotification ) : void;    //执行Command
  • function removeCommand( notificationName : String ):void;        //移除Command
  • function hasCommand( notificationName:String ) : Boolean;        //是否有Command
Controller保存一个数组commandMap,该数组用于保存Notification名与Command类引用的映射。这里需要注意的是Command类是无状态的,只有在需要时才被创建。Command可以获取Proxy对象并与之交互,发送Notification,执行其他的Command。所以执行Command的代码如下:
/**
   * If an <code>ICommand</code> has previously been registered 
   * to handle a the given <code>INotification</code>, then it is executed.
   * 
   * @param note an <code>INotification</code>
   */
  public function executeCommand( note : INotification ) : void
  {
   var commandClassRef : Class = commandMap[ note.getName() ];
   if ( commandClassRef == null ) return;
   var commandInstance : ICommand = new commandClassRef();
   commandInstance.execute( note );
  }
上面就是核心层的相关信息。当然不够全面,大家可以去分析一下,并查看代码的详细注释。
 
Façade
了解了核心类,当然还需要知道如何去用咯,不过对于我们而言,并不需要在实际代码中用到这几个类,PureMVC都替我们做好了。而整个处理过程就是通过Façade了。这也是个单例类,它负责初始化核心层,并能访问它们的public方法。这样,在实际的应用中,只需继承Façade类创建一个具体的Façade类就可以实现整个MVC模式,并不需要在代码中导入Model, View, Controller。
 
具体的代码大家可以自己去看哈,这里就不引用了。呵呵,限于本人英语水平,许多注释只能意会,无法言传。希望大家批评指正。
原创粉丝点击