COMP 310
Fall 2012

Lec13:  Painting continued and Command-Driven Dispatching

Home  Info  Owlspace  Java Resources  Eclipse Resources

Painting continued...

First, we must finish up the previous lecture materials...

Command-Driven Dispatching

For reference, please see the command-dispatching Ballworld with inter-ball interactions demo.     Note:  This is the functionality that you will be creating for HW05, not HW04.

As discussed at the end of the last lecture, the dispatcher shouldn't be considered simply as the conveyor of a single message to the balls, "update!".     One problem that arises out of that viewpoint is that the painting and the state updating processes are coupled together, resulting in artifacts such as the simulation speeding up whenever the frame is resized or an animated GIF is used. 

The dispatcher should send a message (a "command") object to the balls.

But since the ball has no idea a priori what that command is, the only thing that the ball can do is to delegate the interpretation of that command to the one object that knows unequivocally what the command is...the command itelf.

The ball delegates to the command to perform the processing associated with that command.

The balls can be made to do anything one desires simply by sending the appropriate message to them.

Definition:

Strategy -- an abstract behavior/processing that is used by a context object for a specific purpose, e.g. it is used with a known semantic.    Painting and updating the state of the ball are strategies.

Command -- and abstract behavior/processing that is used by the context object without a specific purpose, without a specific semantic.   All the context knows is when to run the command, e.g. whenever it is called to update.  But the context never needs to know what the command is really doing.   Typically, because of the lack of semantic, the command will either have a void return or the context will simply pass any returned values on to something else without doing any additional processing on them -- it can't because the context doesn't know what the results are.

 

Command-based Updating

Instead of merely telling the ball to perform an invariant update method (single method to move, paint, bounce, etc) with an invariant parameter (the Graphics object) being passed, the dispatcher sends out a variant command object that the ball invariantly executes.

A command to the ball to do something is defined as such:

package ballworld.model;

/**
 * Interface that represents commands sent through the dispatcher to process the balls
 * 
 */
public abstract interface IBallCmd {
    /**
     * The method run by the ball's update method which is called when the ball is updated by the dispatcher.
     * @param context The ball that is calling this method.   The context under which the command is to be run.
     * @param disp The Dispatcher that sent the command out.
     */	
    public abstract void apply(Ball context, Dispatcher disp);
}

Notice that the command is given a Ball object when it is executed, so that it knows what ball it is working on.

For instance, the dispatcher may send out a command to update the state:

_dispatcher.notifyAll(_updateStateCmd);

All the ball ever does is

 /**
 * The update method called by the main ball Dispatcher to notify all the balls to perform the given command.
 * The given command is executed.
 * @param o The Dispatcher that sent the update request.
 * @param cmd The IBallCmd that will be run.
 */
public void update(Observable o, Object cmd) {
    ((IBallCmd)cmd).apply(this, (Dispatcher) o);
}

With this, a ball can be made to do whatever you want it to do, whenever you want it to do it!

 

Switching Over To Command-based Dispatching

For now, let's just replicate our current behavior but with a command-based dispatching.

  1. Using the constructs above, change the update code of your ball to take an IBallCmd as its input parameter that it then simply "applies".  
  2. Change the code of in the model for the call to the dispatcher's updateAll method.   Use an anonymous inner class to define the IBallCmd to be sent to the balls (Why do we need an anonymous inner class here?)     Where do you think the code that used to be in the ball's update method now resides?

When you are done, your BallWorld system should run identically as before, but with a new door open to even more possibilities!

Did you have to touch your view code at all?   The controller code?   Why or why not?

For the adventurous: By installing a second Timer object, can you decouple the painting process from the updating of the ball state?   In doing so, can you fix the problem of resizing and animated GIFs affecting the behavior of the balls?

 

 

 

 

 

 


© 2012 by Stephen Wong