Easy patterns: Command

Structure of the Command pattern

This article is created in continuation of easy patterns series description and presents a behavioral pattern named a Command which helps to parametrize clients with different requests and support undoable operations.

Please refer to the other pattern articles as well:

Creational patterns:

Simple Factory

Factory method

Builder

Singleton

Abstract factory

Prototype

Structural patterns:

Adapter

Decorator

Bridge

Composite

Facade

Flyweight

Proxy

Behavioral patterns:

Visitor

Mediator

Observer

Memento

Iterator

Chain Of Responsibility

Strategy

State

Command (this article)

The main essence

Sometimes it’s necessary to issue requests to objects without knowing anything about the operation being requested on the receiver of the request. For example some button section has a button. On click some request should be handled, but button section can’t explicitly implement the request, it should be done by application itself. We do not know the receiver of the request or the operations that will carry it out, only application is aware about that.

This pattern is also known either as an Action or a Transaction.

This pattern includes four main roles:

  • Command — defines a binding between a Receiver object and an Action. Implements an .execute method by invoking the corresponding operation on Receiver.
  • Invoker — asks the Command to carry out the request.
  • Receiver — knows how to perform the operations associtated with carrying out a request.
  • Client — creates a Command object and sets it’s receiver

A few words about roles collaboration.

A collaboration between pattern roles (UML representation)
  1. The client creates a Command object and specifies it’s receiver.
  2. An Invoker object stores the Command object.
  3. An Invoker issues a request by calling .execute on the Command.
  4. In case if Command .execute is undoable Command stores state for undoing the command prior to Invoking the .execute.
  5. The Command object invokes operations on its Receiver to carry out the request.

Commands are an object-oriented replacement for callbacks (functions that are registered somewhere to be called at some later point).

It’s possible to send such action to execute in some other independent place, for example a different process.

The Command .execute operation can store state for reversing its effect inside. So, basically you’re getting not only execute logic encapsulating inside, but also an .undo logic.

Also it’s possible to reapply the logic if the system crash appeared. It happens due to the support of logging. Keeping a persistent log of changes in the system is possible to supply that.

Example of use

In this example we will create a coffee machine. Also we will create an Invoker class with the name ControlPanel, which would invoke a specific command for us by calling it’s .execute method. Each instance of a Command class accepts a CoffeeMachine instance to operate later with. Action class already knows everything it needs for execution. But execution itself is delayed till ControlPanel class decides to do something with that (user button press, etc).

I’ve created here the Command class with abstract methods just to show up the structure of some specific command (each specific command class extends from this Command class).

Profit

Command pattern decouples the object that invokes the operation from the one that knows how to perform it.

Commands usually are the first-class objects (they can be manipulated and extended like any other object).

It’s possible to assemble commands into a composite command (macro command). So it’s possible to execute a groups of command at the same time.

New commands are easy to add because you don’t have to change existing classes.

Weak places

Could be an overhead in cases when decoupling Invoker from the Receiver makes no sense in quite simple logic. In some cases the PubSub pattern just enough to execute callbacks based on events listening.

Conclusion

There are several related patterns that can be used along with a Command pattern:

  • A Composite pattern can be used to make a Macro Commands from simple Command classes.
  • To help with .undo implementation for rolling back the previous state if something goes wrong the Memento pattern can be used.

A Composite pattern helps to structure a system around hign-level operations built on primitives operations. Such structure is common in the systems that support transactions. Each transaction encapsulates a set of changes to data. Basically transactions can be done with a command classes. Commands have a common interface, letting you invoke all transactions the same way. This pattern makes it easy to extend the system with new transactions, just by implementing new command classes.

If you found this article helpful, please hit the 👏 button and feel free to comment below!