Actions
The Command pattern is described in Design Patterns, where menu items are used as an example implementation.
In Swing, the Action interface and the AbstractAction base class implement the Command pattern. They eliminate duplication of code, and separate tasks from the details of their invocation:
- the same Action object can be invoked in multiple ways, usually through a JMenuItem and JToolBar button (JButton and JTextField can also be used)
- text, mnemonic, accelerator, tooltip, command String, and icon are all defined once in an implementation of the Action, and are all shared by all associated graphical elements
- the enabled/disabled state of an Action is always reflected by all associated graphical elements
- Action objects can be passed directly to the constructor of JMenuItem and JButton, and also to JToolBar.add
A JMenuItem corresponding to File->Save can be created
using this Action:
package hirondelle.stocks.file; import java.awt.event.*; import javax.swing.*; import java.util.*; import hirondelle.stocks.portfolio.PortfolioDAO; import hirondelle.stocks.portfolio.CurrentPortfolio; import hirondelle.stocks.util.ui.UiUtil; import java.util.logging.Logger; import hirondelle.stocks.util.Util; /** * Save the edits performed on the {@link CurrentPortfolio}, and update the display * to show that the <tt>CurrentPortfolio</tt> no longer needs a save. */ public final class FileSaveAction extends AbstractAction implements Observer { /** * Constructor. * * @param aCurrentPortfolio is to be saved by this action. */ public FileSaveAction(CurrentPortfolio aCurrentPortfolio) { super("Save", UiUtil.getImageIcon("/toolbarButtonGraphics/general/Save")); fCurrentPortfolio = aCurrentPortfolio; fCurrentPortfolio.addObserver(this); putValue(SHORT_DESCRIPTION, "Save edits to the current portfolio"); putValue( ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK) ); putValue(LONG_DESCRIPTION, "Save edits to the current portfolio"); putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_S)); } @Override public void actionPerformed(ActionEvent e) { fLogger.info("Saving edits to the current portfolio."); PortfolioDAO portfolioDAO = new PortfolioDAO(); portfolioDAO.save(fCurrentPortfolio.getPortfolio()); fCurrentPortfolio.setNeedsSave(false); fCurrentPortfolio.notifyObservers(); } /** * Synchronize the state of this object with the state of the * <tt>CurrentPortfolio</tt> passed to the constructor. * * This action is enabled only when the <tt>CurrentPortfolio</tt> is titled and * needs a save. */ @Override public void update(Observable aPublisher, Object aData) { setEnabled(fCurrentPortfolio.getNeedsSave() && !fCurrentPortfolio.isUntitled()); } // PRIVATE private CurrentPortfolio fCurrentPortfolio; private static final Logger fLogger = Util.getLogger(FileSaveAction.class); }
See Also :
Would you use this technique?