18.2 A Generalized MVC Implementation

 <  Day Day Up  >  

Now that we've learned the theoretical structure of MVC, let's explore a real-world MVC implementation. To get started, we'll create a basic MVC framework that can be reused across many projects. We'll store our core structure in a package called mvc . The classes and interfaces in the mvc package are:


View

An interface all views must implement


Controller

An interface all controllers must implement


AbstractView

A generic implementation of the View interface


AbstractController

A generic implementation of the Controller interface

You'll notice that the model class is conspicuously absent from our mvc package. That's because the model-view relationship in MVC is essentially the same as the Observer pattern we studied in Chapter 16. Hence, we'll use the core code from our existing Observer implementation rather than rewriting similar code for our MVC implementation. The model class in our MVC architecture will be a subclass of Observable , which resides in the package util . The Observer pattern provides the basic services for the model-view relationship ”views register with the model using addObserver( ) and removeObserver( ) , and the model sends updates via the standardized method update( ) , implemented by each view. Hence, in order to register with a model, every view class must implement the util.Observer interface in addition to implementing the mvc.View interface.

By definition, to use the Observable class as the basis of our model class, the model class must extend Observable . If we want our model class to inherit from a different class, we'd have to use the composition-based implementation of the Observer pattern, from Example 16-7.

18.2.1 The View Implementation

Example 18-1 shows the View interface in our mvc package. The View interface defines the basic services every View class must offer, namely:

  • Methods to set and retrieve the controller reference

  • Methods to set and retrieve the model reference

  • A method that returns the default controller for the view

Notice that references to the controller in Example 18-1 must be instances of a class that implements the Controller interface. References to the model must be instances of a class that extends Observable (or, in the composition-based version of the Observer pattern, that implements the Observable interface).

Example 18-1. The View interface
 import util.*; import mvc.*; /**  * Specifies the minimum services that the view  * of a Model-View-Controller triad must provide.  */ interface mvc.View {   /**    * Sets the model this view is observing.    */   public function setModel (m:Observable):Void;   /**    * Returns the model this view is observing.    */   public function getModel ( ):Observable;   /**    * Sets the controller for this view.    */   public function setController (c:Controller):Void;   /**    * Returns this view's controller.    */   public function getController ( ):Controller;   /**    * Returns the default controller for this view.    */   public function defaultController (model:Observable):Controller; } 

To make the View interface easy to implement, we provide AbstractView , a class that implements the basic services defined by the View interface (namely, managing interactions with the controller and model). The AbstractView class also implements the Observer interface. To create a real view class in an MVC application, we need simply extend AbstractView and add code to build and update a user interface. The core MVC grunt work in any real view class is taken care of by AbstractView .

Example 18-2 shows the code for the AbstractView class. Typically, subclasses of AbstractView will create a user interface at construction time and modify that user interface from the update( ) method.

Notice that an instance of the model class must be passed to AbstractView 's constructor. Without that reference, the view cannot query the model for its state. An instance of the controller class can also be passed to the view constructor. However, if you don't supply a controller instance, the AbstractView class uses defaultController( ) to create the controller automatically the first time it is requested (i.e., the first time getController( ) is invoked). Each AbstractView subclass is expected to override defaultController( ) , providing a reference to its own default controller.

Example 18-2. The AbstractView class
 import util.*; import mvc.*; /**  * Provides basic services for the view of a Model-View-Controller triad.  */ class mvc.AbstractView implements Observer, View {   private var model:Observable;       // A reference to the model.   private var controller:Controller;  // A reference to the controller.   public function AbstractView (m:Observable, c:Controller) {     // Set the model.     setModel(m);     // If a controller was supplied, use it. Otherwise let the first     // call to   getController( )   create the default controller.     if (c !== undefined) {       setController(c);     }   }   /**    * Returns the default controller for this view.    */   public function defaultController (model:Observable):Controller {     return null;   }   /**    * Sets the model this view is observing.    */   public function setModel (m:Observable):Void {     model = m;   }   /**    * Returns the model this view is observing.    */   public function getModel ( ):Observable {     return model;   }   /**    * Sets the controller for this view.    */   public function setController (c:Controller):Void {     controller = c;     // Tell the controller this object is its view.     getController( ).setView(this);   }   /**    * Returns this view's controller.    */   public function getController ( ):Controller {     // If a controller hasn't been defined yet...     if (controller === undefined) {       // ...make one. Note that   defaultController( )   is normally overridden        // by   AbstractView   's subclass so that it returns the appropriate       // controller for the view.       setController(defaultController(getModel( )));     }     return controller;   }   /**    * A do-nothing implementation of the   Observer   interface's    *   update( )   method. Subclasses of   AbstractView   provide a concrete    * implementation for this method.    */   public function update(o:Observable, infoObj:Object):Void {   } } 

Now that we have our view defined, let's define the controller.

18.2.2 The Controller Implementation

Example 18-3 shows the Controller interface in our mvc package. The Controller interface defines the basic services every Controller class must offer, namely:

  • Methods to set and retrieve the view reference

  • Methods to set and retrieve the model reference

In the Controller interface, references to the view must be instances of any class that implements the View interface. References to the model must be instances of any class that extends Observable .

Example 18-3. The Controller interface
 import util.*; import mvc.*; /**  * Specifies the minimum services that the controller of  * a Model-View-Controller triad must provide.  */ interface mvc.Controller {   /**    * Sets the model for this controller.    */   public function setModel (m:Observable):Void;   /**    * Returns the model for this controller.    */   public function getModel ( ):Observable;   /**    * Sets the view this controller is servicing.    */   public function setView (v:View):Void;   /**    * Returns this controller's view.    */   public function getView ( ):View; } 

To make controller classes easy to create, we provide AbstractController , a class that implements the basic services defined by the Controller interface to manage interactions with the view and model. To create a real controller class in an MVC application, we need to extend AbstractController and add input-handling code. The core MVC grunt work in any real controller is taken care of by AbstractController .

Example 18-4 shows the code for the AbstractController class. Typically, subclasses of AbstractController implement input event-handling methods that translate user input received from the view into model modification notices sent to the model.

Example 18-4. The AbstractController class
 import util.*; import mvc.*; /**  * Provides basic services for the controller of  * a Model-View-Controller triad.  */ class mvc.AbstractController implements Controller {   private var model:Observable;   // A reference to the model.   private var view:View;          // A reference to the view.   /**    * Constructor    *    * @param   m   The model this controller's view is observing.    */   public function AbstractController (m:Observable) {     // Set the model.     setModel(m);   }   /**    * Sets the model for this controller.    */   public function setModel (m:Observable):Void {     model = m;   }   /**    * Returns the model for this controller.    */   public function getModel ( ):Observable {     return model;   }   /**    * Sets the view that this controller is servicing.    */   public function setView (v:View):Void {     view = v;   }   /**    * Returns this controller's view.    */   public function getView ( ):View {     return view;   } } 

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net