Ultrashock Tutorials > Flash 8 > XML Portfolio Viewer  
 
by Jim Armstrong, 2112 FX::Singularity
Download Source Files 
 
XML Portfolio Viewer
 
 Introduction and Code Requirements 
 Section 01: Layout XML  
 Section 02: Portfolio XML  
 Section 03: Architecture  
 Section 04: Preloading  
 Section 05: Error Handling  
 Section 06: pair & triple classes 
 Section 07: Observer-Observable Utility

 Section 08: Style Manager 
 Section 09: Layout Items  
 Section 10: Custom Layout Classes  
 Section 11: Glyph Class  
 Section 12: Multi-dimensional Thumbnailer  
 Section 13: Model 
 Section 14: View 
 Section 15: Controller 
 Section 16: Suggestions for Improvement 

Observer-Observable Utility

The concept that some components observe other components naturally leads to an implementation of the Observer-Observable pattern. There is a great deal of information regarding this pattern online and it has been covered in Flash tutorials and books such as Moock's EAS2. This section discusses some of the implementation details pertaining to use of this pattern in the portfolio viewer.

Composition or Inheritance

Some Flash (and even most Java) implementations of this pattern begin with an Observable base class that may be extended. Although convenient for most example implementations, extensions of Observable most likely do not have a strong Is-A relationship with Observable. The subclass is essentially borrowing the Observable class' functionality.

Personally, I tend to prefer composition over inheritance unless there exists a strong Is-A relationship. For this reason, the Observer-Observable pattern is implemented with composition. An Observable interface is defined in order to ensure uniform implementation among observable objects. An ObservableObject class is provided that implements the Observable interface. A reference to this class is used by other classes (LayoutItem in this project) that are observable.

Observable

The subject implements certain functionality such as registering observers and notifying observers of updates in subject status. In order to ensure that an observable object contains the required functionality, it must implement the Observable interface.

interface Observable
{
  public function addObserver( _o:Object ):Void;
  public function removeObserver( _o:Object ):Void;
  public function notifyObservers( _info:Object ):Void;
  public function clearObservers():Void;
  public function numObservers():Number;
}

By implementing this interface, we are assured that any observable object has the ability to

- add observers via addObserver()

- remove observers via removeObserver()

- notify observers of changes in subject status via notifyObservers()

- clear the list of observers via clearObsevers()

- report the current number of observers via the numObservers() accessor

ObservableObject

ObservableObject is the utility class that implements the Observable interface. The first section of code is shown below.

import mx.events.EventDispatcher;
class ObservableObject implements Observable
{
  // initialize Event Dispatcher
  private static var INIT_DISPATCHER = 
  EventDispatcher.initialize(ObservableObject.prototype);
  // core
  private var __name:String; // Name of observable object
  private var __observers:Array; // collection of observers
  // Events
  private var dispatchEvent:Function;
  var addEventListener:Function;
  var removeEventListener:Function;
  public function ObservableObject()
  {
    __name = "default";
    __observers = new Array();
  }
.
.
.

Each observable object contains a name and a list of observers.

You may notice that I tend to initialize the EventDispatcher mix-in on the class prototype. This is useful if there are many instances of a given class. The mix-in need only be performed once and the dispatchEvent, addEventListener, and removeEventListener functions are available to any class instance. This method of initialization conserves memory.

Most of the methods in ObservableObject are simple and straightforward, although notifyObservers() looks interesting.

public function notifyObservers( _info:Object ):Void
{
  for( var i=__observers.length-1; i>=0; i-- )
  __observers[i].notify(_info);
};

What is that notify() method?

Observer

In a typical implementation of Observer-Observable, the Observer is required to implement a notify() or similar method to update the observer upon a change in subject status. We might expect there to be an Observer interface to ensure the presence and proper signature of such a method, but there is no such interface in the code base.

Although I confess to being a couple cans short of a six-pack, there is a methodology to this madness. In this application, layout items are implemented with either a LayoutItem class or a class that extends LayoutItem. Since components may observe other components, a LayoutItem may be both an observer and the observed. An example is the SYNOPSIS component; it observes the SCROLLER component and is observed by the PLAY component.

We would normally expect LayoutItem to implement any interface that might be required of an Observer. As it happens, this class also needs to implement other important methods, so its interface is broader than that of a classic Observer.

To see what else is required of a layout item, let's discuss the Style Manager.

 
©2006 Ultrashock.com - All rights reserved