Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Take command of your software

The Command pattern benefits both the client and the server

  • Print
  • Feedback

Page 2 of 5

Figure 1. Command pattern class diagram



In Figure 1, the Invoker class represents an object in an application framework, such as a button or menu item. The Invoker maintains an association with a command through a reference to an object that implements a Command interface, which defines an execute() method. Concrete command classes implement that interface, typically by using an object known as a receiver—application-specific objects that carry out the request. Figure 2 shows a Command pattern sequence diagram.

Figure 2. Command pattern sequence diagram



At runtime, the Invoker calls the Command's execute() method, and the Command invokes a Receiver's method—modeled here as an action() method—that carries out the request.

Swing actions

Almost all OO application frameworks implement the Command pattern, and Swing is no different. This section illustrates how Swing uses the Command pattern to perform application-specific functionality tied to Swing buttons serving as the building blocks for other components, such as menu items or toolbar buttons.

Swing implements the Command pattern with action objects. Whenever you select a Swing menu item or activate a Swing button, those action objects issue a request to an application-specific action. Figure 3 shows a class diagram for Swing actions and how they relate to buttons and menus.

Figure 3. Swing actions class diagram. Click on thumbnail to view full-size image.

Buttons, defined by the AbstractButton class, serve as the Swing workhorses. For simplicity's sake, Figure 3's class diagram does not show all of the classes that ultimately extend AbstractButton because there are many AbstractButton ancestor classes. (Note: Figure 3 also omits most of the AbstractButton methods.) Swing buttons, radio buttons, toggle buttons, check boxes, menus, menu items, check-box menu items, and radio-button menu items are all AbstractButton class extensions. That class maintains a reference to an action defined by the Action interface. You can set or get that reference with the AbstractAction setAction() and getAction() methods, respectively.

Whenever one of the aforementioned Swing components activates, it calls its action's actionPerformed() method, which implements some application-specific functionality. As a convenience, Swing's AbstractAction class eases the implemention of application-specific actions. Let's see how.

Figure 4 shows a Swing application with a single menu featuring two menu items: "show dialog" and "exit." When you activate the "show dialog" menu item, as depicted in Figure 4's top picture, an application-specific action displays the dialog box shown in Figure 4's bottom picture. When you activate the "exit" menu item, another application-specific action terminates the application.



Figure 4. Swing actions in action



The application shown in Figure 4 is listed in Example 1:

Example 1. Two simple Swing actions

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JFrame {
   public static void main(String args[]) { 
      Test frame = new Test();
      frame.setTitle("Swing Actions");
      frame.setSize(500, 400);
      frame.setLocation(400, 200);
      frame.show();
   }
   public Test() {
      JMenuBar mb = new JMenuBar();
      JMenu fileMenu = new JMenu("File");
     fileMenu.add(new ShowDialogAction());
      fileMenu.add(new ExitAction());

      mb.add(fileMenu);
      setJMenuBar(mb);
   }
}
class ShowDialogAction extends AbstractAction {
   public ShowDialogAction() {
      super("show dialog");
   }
   public void actionPerformed(ActionEvent e) {
      JOptionPane.showMessageDialog((Component)e.getSource(),
                               "An action generated this dialog");
   }
}
class ExitAction extends AbstractAction {
   public ExitAction() {
      super("exit");
   }
   public void actionPerformed(ActionEvent e) {
      System.exit(0);
   }
}


The preceding application implements two actions—ShowDialogAction and ExitAction—both of which extend the AbstractAction class. Those classes implement their actionPerformed() methods to implement application-specific functionality; namely, showing a dialog and exiting the application, respectively. The application creates a file menu that's a JMenu class instance and passes instances of ShowDialogAction and ExitAction to that menu's add() method. The add() method creates a menu item—a JMenuItem instance—and associates the action it is passed with the newly created menu item by invoking the menu item's add() method, inherited from AbstractAction, as Figure 3 shows. From then on, the menu items and their actions are wired together: when the menu item is selected, it invokes its action's actionPerformed() method. That method is passed an action event, which provides information about the event, including the component that generated the event. The ShowDialogAction.actionPerformed() method uses that component to create a message dialog. (The ExitAction.actionPerformed() method has no use for the action event it is passed because it simply exits the application.)

  • Print
  • Feedback

Resources