Java ME and the Command Pattern

The Command Pattern provides an efficient workaround for problems you might encounter with Java ME based development.


January 10, 2007
URL:http://www.drdobbs.com/jvm/java-me-and-the-command-pattern/196802806

Darius is a Java consultant at Jayway AB, a Java knowledge company in Sweden. He can be contacted at [email protected].


Command actions in Java ME are handled by the MIDlet class's commandAction() method. While the approach shown in Listing One is quick, neat, and compact, it is also difficult to extend and reuse. The more commands you add, the longer the if-else chain grows—and if you want to use the same command on another screen or canvas, you have to copy-and-paste code, which is difficult to maintain.

public void commandAction(Command command, Displayable d) {
   if (command == firstCommand) {
      textBox.setString("First command executed");
   } else if (command == secondCommand) {
      textBox.setString("Second command run");
   } else if (command == thirdCommand) {
      textBox.setString("Third command chosen");
   } else if (command == exitCommand) {
      notifyDestroyed();
   }
}

Listing One

Luckily, the Command Pattern provides an efficient workaround for these problems. The essence of the Command Pattern is to divide the part where the command is implemented from the part where it is invoked (using a predefined interface, of course; this is object orientation after all). This is done by putting the code behind each command in a separate object, then calling it when it is time.

In Pattern lingua, this translates to: "Encapsulate a request as an object..." (see Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al., Addison-Wesley, 1995) and "the invoker that issues a request on behalf of the client and the set of service-rendering Receiver objects can be decoupled" (see Software Architecture Design Patterns In Java by Partha Kuchana, Auerbach, 2004). In other words, you put the code for the stuff you want to do in a separate object, then call it whenever needed.

For instance, Listing Two(a) illustrates how the commandAction() method might look after applying the Command Pattern. This commandAction() method will never grow due to new commands. A key component here is the AbstractCommand class. It extends Command and is an abstract class that defines the interface (not the Java Interface) that all commands have to use by extending AbstractCommand. Listing Two(b) is the AbstractCommand. As you can see, every command must implement its own execute() method, which is where the action goes. Listing Three illustrates a simple command.

(a)

// Implementation of the CommandListener
public void commandAction(Command command, Displayable d){
   AbstractCommand abstractCommand = (AbstractCommand)command;
   abstractCommand.execute();
}

(b)

public abstract class AbstractCommand extends Command {
   public AbstractCommand(String label, int commandType, int priority) {
      super(label, commandType, priority);
   }
   /* This is where the action goes. */
   public abstract void execute();
}

Listing Two

   
public class MyCommand extends AbstractCommand {
   private TextBox textBox;
   public MyCommand(TextBox t){
      super("Simsalabim", Command.SCREEN, 2);
      textBox = t;
   }
   /* This is where the action is. */
   public void execute() {
      textBox.setString("A rabbit appears");
   }
}

Listing Three

Every command must be configured before it is used. A good place to do this is in the constructor. This lets everything be ready to use as soon as you have an instance of the object. The command in Listing Three is initialized with a TextBox, but it could be anything—adjustable priority, interchangeable canvas, or even different labels for similar commands. It's a bit like the way they use catapults in cartoons. Everything is prepared in advance. Wires are pulled, holders are fastened, and projectiles chosen and carefully inserted. Then it is ready to be used (or "executed") at any time just by pulling a rope. Listing Four(a) shows how you can create and initiate a number of commands in the startApp() method of the MIDlet.

(a)

public void startApp() {
   display = Display.getDisplay(this);
   textbox = new TextBox("Command magic", "Do your magic...", 256, 
      TextField.ANY);
   //Prepare commands
   textbox.addCommand(new ExitCommand(this));
   textbox.addCommand(new MyCommand(textbox));
   textbox.addCommand(new AnotherCommand(textbox));
   textbox.addCommand(new YetAnotherCommand(textbox));
   textbox.setCommandListener(this);
   display.setCurrent(textbox);
}

(b)

public class ExitCommand extends AbstractCommand {
   private MIDlet midlet;
   public ExitCommand(MIDlet m) {
      super("Exit", Command.EXIT, 2);
      midlet = m;
   }
   /* This is where the action is. */
   public void execute() {
      midlet.notifyDestroyed();
   }
}

Listing Four

Of course, you'd have to create the other classes ExitCommand, AnotherCommand, and YetAnotherCommand, too. MIDlet is supplied to the ExitCommand, whereas a TextBox is supplied to the other commands. This is because the ExitCommand must call the notifyDestroyed() method of the MIDlet to initiate its shutdown. Listing Four(b) is what the class looks like.

So different commands can do entirely different things in the execute() method as long as they are properly prepared in the constructor. This is another of the fundamentals behind the Command Pattern. In Pattern lingua: "Concrete Command subclasses specify a receiver-action pair by storing the receiver as an instance variable and by implementing Execute to invoke the request. The receiver has the knowledge required to carry out the request" (Gamma et al.) But now you know what it means. Best of all, you can now reuse the commands with ease on other screens and canvases in the MIDlet.

Threads

A well-known issue with MIDlet programming is that you can't linger in the commandAction() method. For instance, if you check out the CommandListener interface in the Javadocs, you read that the CommandListener method should return immediately. This means that you have to use threads if you do anything that might take time. Luckily, you can use the Command Pattern structure to implement threads in an easy way—just add a class that executes any command in a run() method, and have it implement the Runnable Interface; see Listing Five(a). Then the change to the commandAction() method in Listing Five(b) will have you using threads like never before.

(a)
class CommandExecuter implements Runnable {
   private AbstractCommand command;
   public CommandExecuter(AbstractCommand c) {
      command = c;
   }
   public void run() {
      command.execute();
   }
}

(b) 
// Implementation of CommandListener
public void commandAction(Command command, Displayable d){
   Runnable execute =
      new CommandExecuter((AbstractCommand)command);
   new Thread(execute).start();
}
Listing Five

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.