Applied Design Patterns with Java
Behavioral :: Command (233) {C ch 17}
Intent
Encapsulate a request as an object, to allow parameterizing clients
with different requests, to queue or log requests, and to support 'undo' operations.
As Known As
Action, Transaction
Motivation
It may be necessary to issue requests to objects
without knowing anything about the operation being requested or the receiver of the request. GUI toolkits include
objects like buttons and menus that carry out a request in response to user input. But the toolkit can't implement
the request explicitly in the button or menu, because only applications that use the toolkit know what should be
done on which object. A toolkit designer has no way of knowing the receiver of the request or the operations that
will carry it out.
The Command pattern lets toolkit objects make
requests of unspecified application objects by turning the request itself into an object. This object can be stored and passed around like other objects. The key to this pattern
is an abstract
Command class, which declares an interface for executing operations. This interface includes an
abstract
Execute operation. 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.
Menus can be implemented easily with Command objects. Each choice in a Menu
is an instance of a MenuItem class. An Application class creates these menus and their menu items along with the
rest of the user interface. The Application class also keeps track of Document objects that a user has opened.
The application configures each MenuItem with an instance of a concrete Command subclass. When the user selects
a MenuItem, the MenuItem calls Execute on its command, and Execute carries out the operation. MenuItems don't know which subclass of
Command
they use.
Command
subclasses store the receiver of the request and invoke one or more operations on the receiver. PasteCommand supports
pasting text from the clipboard into a Document. PasteCommand's receiver is the Document object it is supplied
upon instantiation. The Execute operation invokes Paste on the receiving Document.
OpenCommand's Execute operation is different: it prompts the user for
a document name, creates a corresponding Document object, adds the document to the receiving application, and opens
the document.
A MenuItem may need to execute a sequence of commands, like centering
a page at normal size, which could be constructed from a CenterDocumentCommand object and a NormalSizeCommand object.
Because it's common to string commands together in this way, define a MacroCommand class to allow a MenuItem to
execute an open-ended number of commands. MacroCommand is a concrete Command subclass that simply executes a sequence of Commands. MacroCommand has no explicit
receiver, because the commands it sequences define their own receiver.
Notice how the Command pattern decouples the object that invokes the operation from the one having the knowledge to perform it. This gives flexibility in designing a user interface. An application can provide both a menu and a push button interface to a feature just by making the menu and the push button share an instance of the same concrete Command subclass. Commands can be replaced dynamically, which would be useful for implementing context-sensitive menus. This also supports command scripting by composing commands into larger ones. This is possible because the object that issues a request only needs to know how to issue it; it doesn't need to know how the request will be carried out. The underlying feature providing this flexibility is the use of a Delegate, a recurring theme in Design Patterns.