RU beehive logo ITEC dept promo banner
ITEC 120
2007fall
ibarland,
jdymacek

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

lect15c
flexible commands
the command pattern

In explore, we had a big huge if-else statement. If we wanted hundreds of commands, this would get unwieldy. And also there is a maintenence issue: when adding a new command, we'd like to make sure it gets mentioned in the "help" information.

One initial wish might be “I want a List of commands -- that is, a List that contains bare functions.” Java doesn't allow this, but with inheritance we can get close: we can make a class GrueCommand

class LookCommand {
  String commandName = "look";

  /** Have the given explorer perform this 'look' task.
   * @param e The Explorer to perform the 'look' task.
   */
  String perform(Explorer e) { 
    Room here = e.getCurrentRoom();

    // all the code involved in looking around:
    return "You are in " + here.getName() + "\n"
         + "You see " + here.getLoot().toString() + "\n"
         + The exits are " + here.getNeighbors().toString() + "\n";
    }
  }


class GrabCommand {
  String commandName = "grab";


  /** Have the given explorer perform this 'grab' task.
   * @param e The Explorer to perform the 'grab' task.
   */
  String perform(Explorer e) { 
    int treasureIndex = io.promptForInt( "What do you want to pick up? " );
    if (treasureIndex == TextIO.NO_SELECTION_MADE) {
      io.display( "You change your mind." );
      }
    else {
      
      java.util.List<Treasure> localLoot = e.getCurrentRoom().getLoot();
      Treasure t = localLoot.get(treasureIndex);
      io.display( e.grab(t) );
      }
    }

  }

We'd like to have these commands all in a list, so our explore method becomes:

  for (                  c : allCommands ) {
    if (request.equals(c.getCommandName())) {
      c.perform(this);
      }
    }

But we have a problem -- we need each of the above classes to be part of a single class (so that we can name a type for c), and yet we needed them to be in different classes so that we could actually have different code for each perform method.

Solution? Inheritance:

abstract class Command {
  String commandName;

  /** Have the given explorer perform some specific task.
   * @param e The Explorer to perform the specific task.
   */
  abstract String perform(Explorer e);
  }


class LookCommand extends Command { &hellp; }

class GrabCommand extends Command { &hellp; }
Each of these classes is in its own file, and up in class Explorer we can have
  java.util.List<Command> allCommands = new java.util.LinkedList<Command>();
  allCommands.add( new LookCommand() );
  allCommands.add( new GrabCommand() );
  // etc.

(Note that if Java allowed us to pass methods as inputs, this wouldn't have been a difficult problem. In fact, in many languages this is allowed; in those languages “functions are first-class values”, meaning they can be passed to and from methods just like any other value.)

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2007, Ian Barland, Radford University
Last modified 2007.Dec.03 (Mon)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme