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 Pattern is a Design Pattern that does the following:
The Command Pattern has many uses in Java applications, but is commonly seen in:
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.
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 is fairly simple:
Given this background information, lets take a look at two Java Command Pattern examples.
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:
Also, as a negative consequence:
Let's take a look at how the Java API helps us get rid of that negative consequence in our next example.
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.)
Now that you've seen these two Java Command Pattern examples, lets look at the general consequences of using the Command Design Pattern:
The Command Design Pattern is related to other design patterns, and can also be used with other design patterns. For instance:
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