Tuesday, October 09, 2007

Beginner OOP: Observer and Event Delegation Patterns (Part 2)

Now remember last time we talked about the observer design pattern. The observer pattern is very useful because it centralizes information and allows coordination of the interactions between objects.

But there's more. Let's see what's behind door number 2.

The event delegation design pattern is a similar programming strategy. The difference is that this pattern allows multiple types of events. For example, if we write a program which is able to draw a piano keyboard, we might create a class to represent a single key on the keyboard. This single key object might listen to a data model. Now when our keyboard data model tells us that C# is pressed we're not interested in updating the visuals for every key on our keyboard we're only interested in one key. With the event delegation pattern we're able to dispatch a single specific event that will allow only the objects subscribed to this event to be triggered.

Let's talk about terminology. Delegates are objects interested in events. Delegates listen to a specific event fired from a dispatcher. Let's take a look at some simple code to create an event dispatcher. Our event types are actually represented using strings.

To draw an analogy between the observer pattern and the event delegation pattern: Dispatchers are like observables, delegates are like observers, and events are like updates.

class EventHandler {
private var _hash:Object;

public function EventHandler() { }

private function _getListenerIndex($queue:Array, $obj:Object, $listener:String):Number {
for(var i:Number=$queue.length-1; i>=0 &&$queue; i--) {
if($queue[i].l == $listener && $queue[i].o == $obj) return i;
}
return -1; // didn't find anything
}

public function addEventListener($type:String, $obj:Object, $listener:String, $useCapture:Boolean, $priority:Number, $useWeakReference:Boolean):Void {
if(_hash===undefined) _hash={};
if(_hash[$type]===undefined) _hash[$type]=[];
var i:Number=_getListenerIndex(_hash[$type], $obj, $listener);
if(i==-1) {
_hash[$type].push({o:$obj, l:$listener});
}
}

public function dispatchEvent($event:Object):Boolean {
if(!hasEventListener($event.type)) return false;
var queue:Array=_hash[$event.type];
for(var i:Number=queue.length-1; i>=0 &&queue; i--) {
var obj:Object = queue[i].o;
var fxn:String = queue[i].l;
obj[fxn]($event);
}
return true;
}

public function hasEventListener($type:String):Boolean {
if(_hash[$type]!=null && _hash[$type].length>0) return true;
return false;
}

public function removeEventListener($type:String, $obj:Object, $listener:String, $useCapture:Boolean):Void {
if($type!=undefined && $listener==undefined) {
delete(_hash[$type]); return;
}
var i:Number = _getListenerIndex(_hash[$type], $obj, $listener) if(i!=-1)
_hash[$type].splice(i,1);
}

public function removeAllEventListeners():Void {
delete(_hash); }
}

In the above code, we have an object, our hash, which acts as an index for our different event types. Each event type then has a list of delegates. These delegates have methods which will run in their respective scopes.

The addEventListener function will first locates the event list, then if the delegate is not already on the list, it pushes the delegate to the list. When the event occurs our dispatchEvent function locate the event list and call each delegate on the list notifying them that the event has occurred. We also include a removeEventListener function to remove delegates from events.

And there we have it.

After Thought
Now, you might ask why would anyone want to write a whole new event delegation class. Aren't there classes written in Flash which accomplish this? Partly, Flash MX and other provided classes do not run code in their intended functional scopes. This creates a large problem since event delegation is typically deployed inter-object. Classes written to satisfy this need are mostly external classes outside of Flash. Grant Skinner has written a great event class called GDispatcher.

ActionScript 3.0 now uses a similar event model which allows functions to run in their proper scope. In addition, most classes in AS3 now inherit from the EventDispatcher class.

Monday, October 08, 2007

Beginner OOP: Observer and Event Delegation Patterns (Part 1)

I'm going to try to post more frequently. Apologies, my posting has been scarce by any means.

This post is for beginner programmers who want to get into object-oriented programming. Let's talk about design patterns. As you may know object oriented programming is all about objects, creating definitions of them and planning interactions between them.

Now design patterns are about common situations encountered in programming. Implementing them and using them is a common practice for programmers and is the day to day challenge of the object-oriented programmer. Of course, there's always millions of ways to hack around problems and get around things, but hacking code, producing spaghetti code, always creates problems when further changes are later required. Structuring good code while it can take more time initially to plan and carefully understand always shortens the amount of time required to later make changes. Good implementation of design patterns always directly solve problems.

It is possible to use design patterns wrong and to over-program. Remember while programming you should account for changes you will later make, but you don't have to program rules for every situation, only the ones you will encounter. It would be useless to write algorithms for situations that will never occur, all situations should obviously be understood and predetermined as use cases in advance.

The Observer Pattern
So let's talk about a common design pattern that people use frequently, the observer pattern.
Like I said earlier the observer pattern is all about interaction between your code. In the observer design pattern you have several objects which require action when a particular piece of data changes value.

That is you have an object that is observable and an object that is your observer. The object that is the center of attention is the observable, this object has data which you are interested in. When this data changes it sends an update call to all of its observers, who then execute the required actions based on this value change in the interested data.

Code for a simple Observable:
class Observable {
private var _list :Array;
private var _data :String;

public function Observable() {
_list=[];
}

public function register($o:Observer):Void {
_list.push($o);
}

public function set data($s:String):Void {
_data = $s;
_update();
}

public _update():Void {
var n:int=_list.length;
for(var i:int=0; i
}
}


Code for a simple Observer:
public class Observer {
public function Observer() { }

public function update($data:Object):Void {
/* do something exciting! */
}
}


Now to set these classes up and use them:
// let's instantiate them
var parent:Observable = new Observable();
var child1:Observer = new Observable();
var child2:Observer = new Observable();

// let's set it up
parent.register(child1);
parent.register(child2);

// now let's get the parent to
parent.data = "new data woohoo!";


Once the parent changes its data all of its children should then change their data.

This is very useful if you want to create a class to manage your in a class dedicated to being your data model, such as when you use the Model-View-Controller design pattern.

Next time let's talk about the event delegation design pattern.

Thursday, September 20, 2007

Thoughts on Flash vs. Silverlight

Here’s an interesting post:

http://labs.blitzagency.com/?p=381

While the article is not all about Silverlight vs Flash it does raise an interesting point about Silverlight’s opensource tendency. It’s important to note that Blitz Agency works directly with Microsoft.

Personally, I feel that the interactive arena doesn’t need more opensource conventions but it needs stronger experiences. We need designs that speak to users and create better experience for users beyond the common web pages found all across the web. The commonality of the Web may some times be its downfall in that so many “experiences” are merely duplicates of each other; this obviously creates a big problem for brand identity.

My own opinion is that I would personally like to see the direction of the industry moving more towards the direction of Adobe AIR (platform independence, richer capability, self updating infrastructure, … of course this list isn’t mutually exclusive). AIR provides a very strong platform for interactive experiences. Creating an appropriate business model and finding out where the platform can be used is where the next steps are. The more immersive and platform independent an experience can be will ultimately allow us to create better tools and interaction with users. More visibility and more involvement can create richer impressions.

People are already watching movie trailers, catching current events, and even paying their bills with their cell phones. Why should we stop there? As someone working in the interactive industry I feel our greatest challenge is creating new breathtaking experiences.

It would be a nice dream.

Sunday, April 01, 2007

AS3 Kicks Hiney!

I'm working on this new project which will span a year. So it's apparent we may need to upgrade to AS3 at some point and require code migration from AS2 to AS3. Big Spaceship works closely with Adobe and we're running with Flash CS3, the next Flash Professional IDE.

Looks like I've put off learning AS3 long enough. AS3 blows AS2 out of the water. The debugging is so much more stricter, the API is cleaner, the code is more powerful, and the possibilities are endless. There's more on every front.

Guess I should probably throw in the usual shameless plug, go sign up for a preorder of Flash CS3.

Wednesday, November 08, 2006

The best quality Flash

Recently stumbled upon a good piece of FYI at atitightinteractive.com. Quality, by default, is set to quality="high" in Flash. Setting the quality to "best" is a good allows even higher quality to be used. Especially for bitmapped images, this quality difference upgrade can get rid of aliasing, jagged edges, when your images are scaled or rotated.

<object>
...
<param name="quality" value="best">
...
<embed quality="best">
</object>