JavaDesign patterns

Command

The Command pattern encapsulates an operation (or action) in a separated object that contains all information about the operation. In addition to data, each object contains some code to be executed to perform this operation. This pattern decouples the object that invokes the operation from the one that knows how to perform it. It also makes easier to add new operations into the application without modifying existing code.

One of the most common examples of using the Command pattern is organizing interaction between a user interface and core business logic in a modern graphics editor or a complex computer-aided design system. In this case, GUI elements like buttons or menu items after being clicked do not execute logic directly, but they create a command which can be executed regardless of UI elements.

Another example is an application that works with a file system. Each operation like create a file, remove a file and others can be represented as objects.

The classic version

The classic version of the Command pattern has the following elements:

  • The Command interface usually declares just a single method for executing the command.
  • The CocreteCommand is an operation with parameters that pass the call to the receiver; In the classic approach, a command only invokes one or more methods of a Receiver rather than perform business logic.
  • The Client creates a ConcreteCommand object and sets the Receiver.
  • The Invoker asks the command to carry out the request.
  • The Receiver knows how to perform the action.

Note, the interface Command is not necessarily an interface as a language's construct. It can be a simple or abstract class. The main thing is that it represents an abstract command that is inherited by concrete commands.

The following diagram illustrates all the elements of the pattern and their relations.

The command pattern

The Сlient creates an object of Receiver and a ConcreteCommand as well as setting up the Invoker to execute the command. Each type of ConcreteCommand (e.g. CreateFileCommand, RemoveFileCommand) has a set of fields which represent the params. A command calls one or more methods of the Receiver to execute concrete actions to change the state of this application.

Additional options

The Command pattern can be used together with the following options:

  • adding commands to a queue to execute them later
  • supporting undo/redo operations
  • storing a history of commands
  • serializing commands to store them on a disk
  • assembling a set of commands into a single composite command known as macros
These options are not essential to the pattern but are often used in practice.

Sometimes, a command performs all work itself instead of invoking the receiver object to do the action. This version is simpler than classic and also used in practice.

Applicability in practice

Possible applications of this pattern include:

  • GUI buttons and menu items. In Swing programming, an Action is a command object. In addition to the ability to perform the desired command, an Action may have an associated icon, keyboard shortcut, tooltip text, and so on.
  • Networking. It is possible to send whole command objects across the network to be executed on the other machines, for example, player actions in computer games.
  • Transactional behavior. Similar to undo, a database engine or software installer may keep a list of operations that have been or will be performed. Should one of them fail, all others can be reversed or discarded (usually called rollback).
  • Asynchronous method invocation. In multithreading programming, this pattern enables to run commands asynchronous in the background of an application. In this case, the Invoker is running in the main thread and sends the requests to the Receiver which is running in a separate thread. The invoker will keep a queue of commands to be run and will send them to the receiver while it finishes running them.

Conclusion

The main advantage of the command pattern is that it decouples the object that invokes the operation from the one that knows how to perform it. Various modifications of this pattern can be used to keep a history of requests and to implement the undo functionality as well as to create macro commands. However, you should understand that your application can become more complicated because this pattern adds another layer of abstraction instead of simply invoking methods.
How did you like the theory?
Report a typo