A Java Command Design Pattern example

Summary: A Java "Command Pattern" example is demonstrated.

If you've ever seen Java source code that looks like this:

public void actionPerformed(ActionEvent e)
{
  Object o = e.getSource();
  if (o instanceof fileNewMenuItem)
    doFileNewAction();
  else if (o instanceof fileOpenMenuItem)
    doFileOpenAction();
  else if (o instanceof fileOpenRecentMenuItem)
    doFileOpenRecentAction();
  else if (o instanceof fileSaveMenuItem)
    doFileSaveAction();
  // and more ...
}

and you knew it was wrong, but you didn't know how to fix it, you're in the right place. The Command Design Pattern is meant to fix programming problems like this one, as you'll learn below.

The Command Design Pattern

The Command Pattern is a Design Pattern that does the following:

  • Lets you encapsulate actions within Java classes, where each class has an "execute()" method which is declared in the Command interface the class implements.
  • Lets you build your Command objects into a "ready to run" state.
  • Pass those objects to an "invoker" class which makes a callback to the execute() method of each class at the appropriate time.
  • Lets you build an invoker class that doesn't know anything about the logic each Command object contains; it simply knows that it should call the execute() method on an object when an event occurs.
  • Lets you create macros in your applications by building a series of Command objects that have execute() -- and optionally undo() -- methods.

The Command Pattern has many uses in Java applications, but is commonly seen in:

  • Handling actions for Java menu items and buttons.
  • Providing support for macros (recording and playback of macros).
  • Providing "undo" support.
  • Java progress bars.
  • Java wizards.

In all of these cases, implementing Java GUI actions as command objects makes it easier to implement all of these features.

The Command Pattern has other uses, including running the execute() methods at a later time or in parallel processing, but it is seen very commonly in these GUI applications.

Terminology

The Wikipedia article for the Command Pattern defines three terms that are used to describe the Command Design Pattern, and to be consistent, I'll use those terms here as well:

Three terms always associated with the command pattern are client, invoker and receiver. The client instantiates the command object and provides the information required to call the method at a later time. The invoker decides when the method should be called. The receiver is an instance of the class that contains the method's code (the execute() method of the class).

Implementing the Command Pattern in Java

Implementing the Command Pattern in Java is fairly simple:

  1. Define a Java Command interface with a method named execute(). (You can name it anything you want, but it is classically named execute().)
  2. Create Command classes that implement this interface. The execute() method of each object will contain the logic specific to the action you are encapsulating. (For instance, you might create a FileOpenCommand and a FileCloseCommand in a text editor application.)
  3. In an Model/View/Controller GUI program you will have a controller class that constructs each of your Command objects. (The Wikipedia "client" class.)
  4. Each of these "ready to run" command objects is passed to an invoker class.
  5. The invoker class calls the execute() method of a Command object at the appropriate time. In a GUI application this may happen when a user selects a menu item or presses a button.

Given this background information, lets take a look at two Java Command Pattern examples.

A Java Command Pattern example (Example #1)

In our first example, a book named Java Design Patterns by James Cooper has some nice "before" and "after" code that demonstrates the Command Pattern in Java, and I'd like to share a variation of that here.

If you've ever seen some old Java GUI code, or perhaps have seen GUI code written by a new developer, you might run across an actionPerformed() method in a Swing application that looks like this:

public void actionPerformed(ActionEvent e)
{
  Object o = e.getSource();
  if (o = fileNewMenuItem)
    doFileNewAction();
  else if (o = fileOpenMenuItem)
    doFileOpenAction();
  else if (o = fileOpenRecentMenuItem)
    doFileOpenRecentAction();
  else if (o = fileSaveMenuItem)
    doFileSaveAction();
  // and more ...
}

When I see code like this I actually smile, because it reminds me of my own struggles many years ago. As you might guess, this code becomes very hard to maintain, and you'll have as many "if" statements as menu items. But what else can you do?

A Java Command Pattern solution

The solution to this problem is to implement the Command Design Pattern in your Java application. Here are the steps we follow to implement the Command Pattern:

1) We create a simple Java Command interface, like this:

// the Command Pattern in Java
public interface Command
{
  public void execute();
}

2) Next, we modify our JMenuItem and JButton classes to implement our Command interface, as shown here:

public class FileOpenMenuItem extends JMenuItem implements Command
{
  public void execute()
  {
    // your business logic goes here
  }
}

As you might guess, each of these classes is small, containing just enough logic to implement its own action.

3) Next, we add our menu items and buttons to our application as we did before. (I won't show that here, because this portion of the application doesn't change. Also, Example #2 below shows an improvement on this first example, so I don't want you to go too far with this approach.)

4) Finally, after these changes, our new actionPerformed() method in our ActionListener class looks like this:

public void actionPerformed(ActionEvent e)
{
  Command command = (Command)e.getSource();
  command.execute();
}

Now, isn't that a nice and clean actionPerformed() method? Right away you can see some consequences of our Java Command Pattern design:

  • The actionPerformed() method is much simpler.
  • All of the "if" statements in the actionPerformed method have been eliminated.
  • We have a new Java Command interface.
  • We have a collection of small Java classes that implement the Command interface. The logic for each action is small, and self-contained in each execute() method.
  • The actionPerformed method has no idea what actual Command it is running.

Also, as a negative consequence:

  • Each JMenuItem and JButton must implement the Command interface.

Let's take a look at how the Java API helps us get rid of that negative consequence in our next example.

A better Java Command Pattern example (Example #2)

Now that I've demonstrated this Java Command Pattern example using a home-brewed interface, I think there's an even better solution to this problem.

As mentioned above, a negative consequence of this implementation is that each of our menu items and buttons must implement the Command interface. If you're using a GUI builder, as I have been known to do, this is impossible. Beyond that, there's no need to do this in a Java application.

A better solution is to use the Java Action interface or the Java AbstractAction class. I demonstrate this solution in my complete Java Action, AbstractAction, and ActionListener example. That tutorial is a complete example of how to use the Java Action interface and AbstractAction class in a way that closely mirrors the Command Pattern.

The only important difference is that the designers of the Java Swing API saw the need to provide the "Action" interface in their GUI elements, so classes like JMenuItem and JButton are already wired to accept Action objects, and they know to call the actionPerformed() method of those objects when an event occurs. (As opposed to you writing logic to call the execute() method of your own Java Command Pattern classes.)

Consequences of the Command Pattern

Now that you've seen these two Java Command Pattern examples, lets look at the general consequences of using the Command Design Pattern:

  • The object that invokes the operation is decoupled from the object that knows how to perform the action. (The "invoker" is decoupled from the "receiver".) As a result, that action can easily be changed without requiring a corresponding change in the invoker.
  • Command objects can be assembled into a sequence of composite commands. In fact, this is how "macro" commands are created in most GUI applications.
  • In some implementations of the Command Pattern there can also be a "time separation". That is, your Command object is considered a pre-packaged, ready to run object that can be implemented at some future time.

Related Design Patterns

The Command Design Pattern is related to other design patterns, and can also be used with other design patterns. For instance:

  • Chain of Responsibility can use Command objects to represent requests as objects.
  • Command and Memento act as objects which can be passed around and invoked at a later time. In Command the object represents an action (or response to a client event), while in Memento the object represents the internal state of an object at a particular time.
  • A combination of Commands can be used to create macros with the Composite Design Pattern.

A Java Command Pattern example - Summary

I hope this explanation of the Command Design Pattern -- and the two Java Command Patterns example shown here -- have been helpful. If you have any questions or comments, please leave a note in the Comments section below.

Good Article on Command Pattern

very helpful....please cover Memento
:)

great simple and clear explanation!

Thanks, this is much clearer than the wikipedia article :)

Post new comment

The content of this field is kept private and will not be shown publicly.