tim richter

The following post discusses an "extended" version of the Observer-Pattern.

The intent of the observer pattern is often described as an one-to-many dependency.
The key fact is that when one object changes its state, all listeners are notified about that change [GHJV95].

There are only two relevant kinds of objects in this pattern, observers and an observable.

An observable is basically an object that holds information on which other objects (observer) could be interested in.
When the data-state of the observable has changed the observers are notified about the change.
This kind of interaction is called publish-subscribe. The observable is the publisher of notifications. It sends out these notifications without having to know who its observers are[GHJV95].

So good so far...

Now let's examine the concrete implementation of an extended scenario.
extended observer pattern

The extended part in this observer pattern is the ISpecificObserver interface. If only specific notifications are interesting for an observer, it has to implement the ISpecificObserver interface and return an Array of notification interests (acceptedNotifications():Array).

Here are the interesting parts of the Observable:

public function addObserver( o: IObserver ): void
{
	if( o is ISpecificObserver )
	{
		var notifications: Array = ISpecificObserver( o ).acceptedNotifications();
		var len: int = notifications.length;
		var list: ISet;
 
		while( --len > -1 )
		{
			list = _specificObservers.getValue( notifications[ len ] );
 
			if( list == null )
			{
				list = new ArraySet();
 
				_specificObservers.put( notifications[ len ], list );
			}
 
			list.add( o );
		}
	}
	else if( o is IObserver )
	{
		_observers.add( o );
	}
}
public function notifyObservers( type: String = null, data: * = null ): void
{
	var node: LinkedNode;
 
	if( type != null )
	{
		var list: LinkedSet = LinkedSet( _specificObservers.getValue( type ) );
 
		if( list != null )
		{
			// -- notify all ISpecificObserver
			node = list.firstNode;
 
			while( ( node = node.post ) != null )
			{
				ISpecificObserver( node.value ).update( this, type, data );
			}
		}
	}
	else
	{
		type = DataNotificationType.GENERIC;
	}
 
	// -- notify all IObserver
	node = _observers.firstNode;
 
	while( ( node = node.post ) != null )
	{
		IObserver( node.value ).update( this, type, data );
	}
}

An concrete implementation could look like this:

package
{
	import com.addicted2flash.data.DataNotificationType;
	import com.addicted2flash.util.IObservable;
	import com.addicted2flash.util.ISpecificObserver;		
 
	/**
	 * @author Tim Richter
	 */
	public class ObserverExample implements ISpecificObserver
	{
		public function ObserverExample()
		{
		}
 
		public function acceptedNotifications(): Array
		{
			return [ DataNotificationType.COMPLETE ];
		}
 
		public function update( observable: IObservable, type: String, data: * ): void
		{
			switch( type )
			{
				case DataNotificationType.COMPLETE:
					// -- do something!
					break;
			}
		}
	}
}

References:

[GHJV95] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns – Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995

5 COMMENTS
ad

[...] In this case it is recommended to use a more dynamic approach like an specific observable. [...]

ad

[...] – Extended Observer-Pattern saved by kiyotin2009-05-13 – hounds, camera, sock saved by OkitaAoyagi2009-04-29 – Retreat saved by [...]

ad

[...] searched for similar AS3 Observer implementation examples online and found but one. Hope my example helps your code find its way to clean & [...]

March 20, 2010
ad

seem interesting…

But i want to ask some more… i just wanna discuss so no offense, ok ?

To my understand, if you has 10 Observable then you will need to make 10 more ISpecificObserver ?

How about add one more +observerName():String for IObservable and one more acceptNotifications(name: String): Array for IObserver, then we do not need ISpecificObsever anymore ?

This way, when we need a concreteObserver to listen to 10 Observable we can do a simple switch case inside acceptNotifications, according to the name, we return the correct interested notifications array ?

Actually i am addicted to flash, too and if you want to discuss more can we talk through email / chat ?

thanks.

tim
March 22, 2010
ad

the only problem with this approach is that a concrete implementation accepts the same notifications for every IObservable. This is why the oberver implementations in the a2f-library are different. Another way to get around this issue is to pass the interests as parameters.

regards
tim

Post a comment