March 24, 2004
The many faces of EventDispatcher
So there's more or less 3 different schools of thought for implementing EventDispatcher in your classes. I've attempted to summarize the three most common approaches that I've seen, as well as the pros and cons of each approach. This is by no means a definitive list, but rather just a list from my perspective as an application developer. Feel free to add to it or contradict me in the comments.
-
Using a static initializer in the class:
This approach looks like this...
private static var EventDispatcher_mixin = EventDispatcher.initialize(MyClass.prototype);
In this approach, the class is responsible for declaring function variables for addEventListener, removeEventListener, and dispatchEvent. Then, the actual method implementations are mixed in from EventDispatcher to the class' prototype allowing the instances to use the EventDispatcher functionality themselves without further reliance on EventDispatcher.
Pros:
- The methods are mixed into the class prototype, thus saving memory and improving instantiation performance. The methods are only copied from EventDispatcher one time, so every time your class is instantiated the instance will automatically have the methods available to it through the prototype.
- Out of all the approaches I touch on, this one has the least overhead.
Cons:
- See the word prototype in there? It hasn't been deprecated, but who knows how long ActionScript classes will be compiled down to prototypes. Maybe this is really a non-issue, but I wouldn't want to have to re-write all of my classes in the future to work with Flash Player X if the runtime implementation changes.
- Really, the class should implement an "EventBroadcaster" interface so that the intention of the class is made known at compile-time. Yes, the class will have a "public var addEventListener:Function;" in it, but interfaces in ActionScript can only define methods, so you can't implement an interface. Thus the intent to dispatch events is not made explicit at compile-time, which could be construed as a design shortcoming.
- Something about that code just looks "ugly" and screams "hack" to me. Of course, that's totally my opinion...
Further reading:
-
Using the constructor to initialize the instance as an event source:
This approach looks like this...
// in the constructor EventDispatcher.initialize(this);
This approach is much the same as above. However, instead of initializing the prototype of the class, each instance of the class has to be initialized as an event source. In a singleton situation, this should provide roughly the same performance as copying the methods to the prototype. If you're going to be creating a lot of instances though, the performance of the constructor will be slightly slower (not by much though).
Pros:
- See the word prototype in there? Nope, not at all. Doing things this way is almost the same as above, except we're not relying on the underlying run time implementation for functionality.
- I think this approach is a little cleaner than the approach above, as far as readability is concerned.
Cons:
- Like the above approach, some sort of event broadcasting interface should be implemented. The class in this situation again needs to define function variables that get their implementations mixed in, but again, interfaces cannot define variables in AS 2.
- As stated, there are slight performance penalties for each instantiation.
- Some will argue that this code is redundant, since we're doing the same thing for every instance when it makes more sense to do it once at the class level.
Further reading:
-
Using composition:
This approach looks like this...
// in class body private var eventSrc:Object // in constructor EventDispatcher.initialize(eventSrc); // methods: public function registerView(view) { eventSrc.addEventListener("change", view); // more... } public function removeView(view) { eventSrc.removeEventListener("change", view); // more... } private function doSomething() { var eventObj:Object = new Object(); eventObj.target=this; eventObj.type = "change"; eventSrc.dispatchEvent(eventObj); }
This approach is radically different. Instead of making the instance the event source, we're using composition to create an object that will be the source of the events for a particular instance. Then, instead of defining function variables that are mixed in, we're instead providing methods to register views (think MVC) that will automatically register the view for all of the applicable events via addEventListener on the eventSrc.
Pros:
- By using this approach, the intent can be made clear since we can finally implement an event broadcasting interface because there are no functions declared as variables. In this situation, we would implement an interface that defines the registerView and removeView methods.
- Again, there are no prototype tricks here. This is straight-up legit, "still-works-even-if-prototype-dies" code.
- I think this approach provides the most flexibility. If we want to change to AsBroadcaster instead of EventDispatcher we can just modify the event source and the few lines in registerView and removeView. The interface for our class stays consistent then with minimal effort. If we were using one of the previous 2 approaches we would have to make addEventListener a method that would invoke addListener, or we would have to update the interface and therefore force users of our class to change their code as well.
Cons:
- This method provides a bit of overhead for the extra function call to register the view.
- Like the above approach, we're initializing the eventSrc in the constructor, so every instance being created will have a slight performance hit.
- Obviously, registerView is somewhat specific to the MVC design pattern, but that may not be a con... I tend to use the MVC design pattern a lot in my Flash applications. You could, of course, just change the method name.
Further reading:
So, there you go.. that's my take on using EventDispatcher. I tend to use the third approach, composition, for the reasons listed above. Of course, you're free to use whatever method you like best. If you have anything to add, go ahead and leverage the comments.

Comments
I've been using something similiar to approach number 3, for the simple purpose of it just looks cleaner :)
Good read though :)
Posted by: Scott Barnes at March 24, 2004 08:22 PM
Haven't used 3 before... I'll have to try it out and see how she feels. Thanks for the article!
Posted by: JesterXL at March 24, 2004 08:35 PM
I lean towards #2 for cleanliness. If performance is really an issue, which w/ v2 components it quickly can be, I just use good ol' ASBroadcaster.
Posted by: Brian at March 24, 2004 08:46 PM
Nicely covered ... I think all three approaches probably have their place. Although, I have to admit that I haven't used #3 myself. If I were writing the class only for internal use, I might even use the interface you describe in #3, but if it were for public distribution I'd probably stay with the interface defined by IEventDispatcher because it's already known and documented among the Flash world.
Posted by: Sean Voisen at March 24, 2004 09:18 PM
nice one, darron. as you mention, the performace difference between all three is almost negligible, so it mostly becomes a matter of aesthetics... i personally don't like #1, and #3 looks ok... like brian, i lean towards #2 for cleanliness
Posted by: eokyere at March 24, 2004 09:26 PM
There is another option, which is to make a generic dispatcher class that you can instantiate. This is something I used to do with ASBroadcaster in MX. (see my blog post at http://www.peterjoel.com/blog/index.php?archive=2003_04_27_archive.xml#93642758).
With the class, you can either inherit from it or use composition, as in your 3rd option but even cleaner! :) The nice thing about inheriting or composing, is that you can extend the methods, which I have occasionally had cause to do.
In practise, I use the first option, but that is really out of laziness because I never got around to deciding what package to put the instantiable version in! However I do it slightly differently; instead of declaring the methods as properties of type Function, I declare them as empty functions, with full signatures. This little detail means that I still get full type checking on arguments and return types.
Posted by: Peter Hall at March 24, 2004 09:55 PM
I prefer the third approach also, although in most cases, I make my classes inherit from a generic dispatcher class. I think this both approaches are the most flexible.
Posted by: Cesar Tardaguila at March 25, 2004 04:06 AM
in seans original post I was using what you show in method 3. However, once I added in more composed classes and implemented other interfaces the code started to become a little messy. So I started using my own Dispatch class like Peter mentions.
I do like the concept of mixins but with the lack of support for multiple inheritance the code can get a little out of hand.
Posted by: erik bianchi at March 25, 2004 11:14 AM
I'm not sure how I feel about mix-ins. They work well and are convenient... but letting one object write methods to another just doesn't feel right.
Posted by: Paul at March 26, 2004 05:22 AM
Hey Paul,
Just to clarify a mixin doesn't have to write methods to a class in the way that EventDispatcher does. By definition a mixin is just a class that adds in specific functionality (i.e. clickable, selectable, draggable, etc) and was originally designed for multi-inheritance languages. The way ASBroadcaster and EventDispatcher works is just the way Macromedia decided to implement that functionality.
Posted by: erikbianchi at March 26, 2004 10:46 AM
Gotchyah. Thanks.
Posted by: Paul at March 26, 2004 07:37 PM
// Corespondent class
// usage:
// in class declaration:
// var events:Corespondent;
// in constructor: events = new Corespondent(this);
// registration: mySource.events.addEventListener(myAudience)
import mx.events.EventDispatcher;
class Corespondent
{
// EventDispatcher mixin interface
var addEventListener:Function;
var dispatchEvent:Function;
var removeEventListener:Function;
private var myRespondent:Object;
static var init:Boolean;
private static function initialize():Boolean
{
if ( init == true ); else EventDispatcher.initialize(Corespondent.prototype);
return true;
}
function Corespondent(respondent:Object)
{
initialize();
myRespondent = respondent;
}
function broadcastMessage(evtObj:Object)
{
evtObj.respondent = myRespondent;
dispatchEvent(evtObj);
}
}
Posted by: George Polevoy at April 24, 2005 08:23 AM
I know this is a really stupid question, does anyone know where i could get a MVC pattern using the EventDispatch framework from anywhere? What i mean maybe a guide of some sort. I been trying to use it with my MVC pattern and i just dont get. Any help would be great.
Posted by: Joe Jordan at May 2, 2005 11:12 AM