/* PureMVC - Copyright(c) 2006-08 Futurescale, Inc., Some rights reserved. Your reuse is governed by the Creative Commons Attribution 3.0 United States License */ package org.puremvc.as3.patterns.facade { import org.puremvc.as3.core.*; import org.puremvc.as3.interfaces.*; import org.puremvc.as3.patterns.observer.Notification; /** * A base Singleton IFacade implementation. * *

* In PureMVC, the Facade class assumes these * responsibilities: *

*

* Example usage: *

* import org.puremvc.as3.patterns.facade.∗; * * import com.me.myapp.model.~~; * import com.me.myapp.view.~~; * import com.me.myapp.controller.~~; * * public class MyFacade extends Facade * { * // Notification constants. The Facade is the ideal * // location for these constants, since any part * // of the application participating in PureMVC * // Observer Notification will know the Facade. * public static const GO_COMMAND:String = "go"; * * // Override Singleton Factory method * public static function getInstance() : MyFacade { * if (instance == null) instance = new MyFacade(); * return instance as MyFacade; * } * * // optional initialization hook for Facade * override public function initializeFacade() : void { * super.initializeFacade(); * // do any special subclass initialization here * } * * // optional initialization hook for Controller * override public function initializeController() : void { * // call super to use the PureMVC Controller Singleton. * super.initializeController(); * * // Otherwise, if you're implmenting your own * // IController, then instead do: * // if ( controller != null ) return; * // controller = MyAppController.getInstance(); * * // do any special subclass initialization here * // such as registering Commands * registerCommand( GO_COMMAND, com.me.myapp.controller.GoCommand ) * } * * // optional initialization hook for Model * override public function initializeModel() : void { * // call super to use the PureMVC Model Singleton. * super.initializeModel(); * * // Otherwise, if you're implmenting your own * // IModel, then instead do: * // if ( model != null ) return; * // model = MyAppModel.getInstance(); * * // do any special subclass initialization here * // such as creating and registering Model proxys * // that don't require a facade reference at * // construction time, such as fixed type lists * // that never need to send Notifications. * regsiterProxy( new USStateNamesProxy() ); * * // CAREFUL: Can't reference Facade instance in constructor * // of new Proxys from here, since this step is part of * // Facade construction! Usually, Proxys needing to send * // notifications are registered elsewhere in the app * // for this reason. * } * * // optional initialization hook for View * override public function initializeView() : void { * // call super to use the PureMVC View Singleton. * super.initializeView(); * * // Otherwise, if you're implmenting your own * // IView, then instead do: * // if ( view != null ) return; * // view = MyAppView.getInstance(); * * // do any special subclass initialization here * // such as creating and registering Mediators * // that do not need a Facade reference at construction * // time. * registerMediator( new LoginMediator() ); * * // CAREFUL: Can't reference Facade instance in constructor * // of new Mediators from here, since this is a step * // in Facade construction! Usually, all Mediators need * // receive notifications, and are registered elsewhere in * // the app for this reason. * } * } * * * @see org.puremvc.as3.core.model.Model Model * @see org.puremvc.as3.core.view.View View * @see org.puremvc.as3.core.controller.Controller Controller * @see org.puremvc.as3.patterns.observer.Notification Notification * @see org.puremvc.as3.patterns.mediator.Mediator Mediator * @see org.puremvc.as3.patterns.proxy.Proxy Proxy * @see org.puremvc.as3.patterns.command.SimpleCommand SimpleCommand * @see org.puremvc.as3.patterns.command.MacroCommand MacroCommand */ public class Facade implements IFacade { /** * Constructor. * *

* This IFacade implementation is a Singleton, * so you should not call the constructor * directly, but instead call the static Singleton * Factory method Facade.getInstance() * * @throws Error Error if Singleton instance has already been constructed * */ public function Facade( ) { if (instance != null) throw Error(SINGLETON_MSG); instance = this; initializeFacade(); } /** * Initialize the Singleton Facade instance. * *

* Called automatically by the constructor. Override in your * subclass to do any subclass specific initializations. Be * sure to call super.initializeFacade(), though.

*/ protected function initializeFacade( ):void { initializeModel(); initializeController(); initializeView(); } /** * Facade Singleton Factory method * * @return the Singleton instance of the Facade */ public static function getInstance():IFacade { if (instance == null) instance = new Facade( ); return instance; } /** * Initialize the Controller. * *

* Called by the initializeFacade method. * Override this method in your subclass of Facade * if one or both of the following are true: *

* If you don't want to initialize a different IController, * call super.initializeController() at the beginning of your * method, then register Commands. *

*/ protected function initializeController( ):void { if ( controller != null ) return; controller = Controller.getInstance(); } /** * Initialize the Model. * *

* Called by the initializeFacade method. * Override this method in your subclass of Facade * if one or both of the following are true: *

* If you don't want to initialize a different IModel, * call super.initializeModel() at the beginning of your * method, then register Proxys. *

* Note: This method is rarely overridden; in practice you are more * likely to use a Command to create and register Proxys * with the Model, since Proxys with mutable data will likely * need to send INotifications and thus will likely want to fetch a reference to * the Facade during their construction. *

*/ protected function initializeModel( ):void { if ( model != null ) return; model = Model.getInstance(); } /** * Initialize the View. * *

* Called by the initializeFacade method. * Override this method in your subclass of Facade * if one or both of the following are true: *

* If you don't want to initialize a different IView, * call super.initializeView() at the beginning of your * method, then register IMediator instances. *

* Note: This method is rarely overridden; in practice you are more * likely to use a Command to create and register Mediators * with the View, since IMediator instances will need to send * INotifications and thus will likely want to fetch a reference * to the Facade during their construction. *

*/ protected function initializeView( ):void { if ( view != null ) return; view = View.getInstance(); } /** * Register an ICommand with the Controller by Notification name. * * @param notificationName the name of the INotification to associate the ICommand with * @param commandClassRef a reference to the Class of the ICommand */ public function registerCommand( notificationName:String, commandClassRef:Class ):void { controller.registerCommand( notificationName, commandClassRef ); } /** * Remove a previously registered ICommand to INotification mapping from the Controller. * * @param notificationName the name of the INotification to remove the ICommand mapping for */ public function removeCommand( notificationName:String ):void { controller.removeCommand( notificationName ); } /** * Check if a Command is registered for a given Notification * * @param notificationName * @return whether a Command is currently registered for the given notificationName. */ public function hasCommand( notificationName:String ) : Boolean { return controller.hasCommand(notificationName); } /** * Register an IProxy with the Model by name. * * @param proxyName the name of the IProxy. * @param proxy the IProxy instance to be registered with the Model. */ public function registerProxy ( proxy:IProxy ):void { model.registerProxy ( proxy ); } /** * Retrieve an IProxy from the Model by name. * * @param proxyName the name of the proxy to be retrieved. * @return the IProxy instance previously registered with the given proxyName. */ public function retrieveProxy ( proxyName:String ):IProxy { return model.retrieveProxy ( proxyName ); } /** * Remove an IProxy from the Model by name. * * @param proxyName the IProxy to remove from the Model. * @return the IProxy that was removed from the Model */ public function removeProxy ( proxyName:String ):IProxy { var proxy:IProxy; if ( model != null ) proxy = model.removeProxy ( proxyName ); return proxy } /** * Check if a Proxy is registered * * @param proxyName * @return whether a Proxy is currently registered with the given proxyName. */ public function hasProxy( proxyName:String ) : Boolean { return model.hasProxy( proxyName ); } /** * Register a IMediator with the View. * * @param mediatorName the name to associate with this IMediator * @param mediator a reference to the IMediator */ public function registerMediator( mediator:IMediator ):void { if ( view != null ) view.registerMediator( mediator ); } /** * Retrieve an IMediator from the View. * * @param mediatorName * @return the IMediator previously registered with the given mediatorName. */ public function retrieveMediator( mediatorName:String ):IMediator { return view.retrieveMediator( mediatorName ) as IMediator; } /** * Remove an IMediator from the View. * * @param mediatorName name of the IMediator to be removed. * @return the IMediator that was removed from the View */ public function removeMediator( mediatorName:String ) : IMediator { var mediator:IMediator; if ( view != null ) mediator = view.removeMediator( mediatorName ); return mediator; } /** * Check if a Mediator is registered or not * * @param mediatorName * @return whether a Mediator is registered with the given mediatorName. */ public function hasMediator( mediatorName:String ) : Boolean { return view.hasMediator( mediatorName ); } /** * Create and send an INotification. * *

* Keeps us from having to construct new notification * instances in our implementation code. * @param notificationName the name of the notiification to send * @param body the body of the notification (optional) * @param type the type of the notification (optional) */ public function sendNotification( notificationName:String, body:Object=null, type:String=null ):void { notifyObservers( new Notification( notificationName, body, type ) ); } /** * Notify Observers. *

* This method is left public mostly for backward * compatibility, and to allow you to send custom * notification classes using the facade.

*

* Usually you should just call sendNotification * and pass the parameters, never having to * construct the notification yourself.

* * @param notification the INotification to have the View notify Observers of. */ public function notifyObservers ( notification:INotification ):void { if ( view != null ) view.notifyObservers( notification ); } // Private references to Model, View and Controller protected var controller : IController; protected var model : IModel; protected var view : IView; // The Singleton Facade instance. protected static var instance : IFacade; // Message Constants protected const SINGLETON_MSG : String = "Facade Singleton already constructed!"; } }