Generic Responder – Good for Command Pattern

When implementing the Command pattern for this game concept I’m working on at home, I had a need for the command to also support an “executed” method. Typically, it executes, and that’s the end of it.

However, I’m managing the commands in a Queue/Stack of sorts, and need to know when the command is done. Since the command class really has little coupling with the source that it’s actually calling the command on, I created a Responder class that they all could share. The issue is, however, there is no way to create these in such a way to merely have a method, execute it when the even happens, and then go away.

Granted, my class could implement the event, and using GDispatcher, execute it, but these events are asyncronous, and I don’t want the command adding himself as a listener to the “receiver”, or the class he’s executing the command on. Everything now is nicely coupled only via methods or explicit setting via the Controller. It’s an abstract pain in the arse, but so far the code is beautiful and flexible. Thus, the Responder needed to have a Singleton’esque ability to create instances of himself for one time uses, but have enough knowledge of the method he’s calling since the class who is using him cares not what even happens to him. The usual way is when you create a responder, you hold onto it, or map it back to yourself; like Remoting/Central responder objects either map to functions in your class or are generic responder objects that execute in your class’ scope. If you don’t care, what do you do?

I created a static method of my responder class to create one-time event listeners that call a method, pass what args you need, and assumably die when done. This way, my Command class could execute the command, and get the generic responder object as the return value. The receiver, or the class getting the command executed upon it, could return this responder, and when his event is done, merely have the responder inform the command class without having to worry about caring about the responder objects after that point.

Since the Command class adds himself as a listener, he’ll be able to generate events on when commands are started and stopped (and any number of mods such as “undo” in the future), and this then supports a nice way for the Queue to know wtf is going on.

Observe the method; the entire class is at the bottom.

static function createGenericResponder(method:String):Object
{
        var o:Object = {};
        grantskinner.events.GDispatcher.initialize(o);
        o.method = method;
        o[method] = function()
        {
                dispatchEvent({type: this.method, target: this, results: arguments});
        };
        return o;
}

Here’s an example of a function called via the Command class, and the reciever returning the generic responder which he’ll call when an animation is done.

public function attack(targets_array:Array):Object
var o:Object = jxl.events.Responder.createGenericResponder("onDoneAttacking");
this.gotoAndPlay(ATTACKING_START);
doWhenFrameReached("onDoneAttacking", this, this, ATTACKING_END, o);
return o;
}

And the Responder class it sits in:

class jxl.events.Responder
{
        static var inited:Boolean;
        
        public var addEventListener:Function;
        public var removeEventListener:Function;
        private var dispatchEvent:Function;
        
        function Responder()
        {
                if(!inited){
                        inited = true;
                        grantskinner.events.GDispatcher.initialize(Responder.prototype);
                }
        }
        
        public function onResult()
        {
                dispatchEvent({type: "result", target: this, results: arguments});
        }
        
        public function onStatus()
        {
                dispatchEvent({type: "status", target: this, results: arguments});
        }
        
        static function createGenericResponder(method:String):Object
        {
                var o:Object = {};
                grantskinner.events.GDispatcher.initialize(o);
                o.method = method;
                o[method] = function()
                {
                        dispatchEvent({type: this.method, target: this, results: arguments});
                };
                return o;
        }
}