Command Pattern
The Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.
Bates and Sierra — Head First Design Patterns
Class diagram
/images/posts/design-patterns/command_pattern.png
Client
creates theConcreteCommand
and sets itsReceiver
.Receiver
knows how to perform the work to carry out the request.ConcreteCommand
defines a binding between an action and aReceiver
.Invoker
makes a request calling execute() method, theConcreteCommand
carries the request out calling one or more actions on theReceiver
.
##Key Points
##Command in Action Scenario. The idea is to implement a remote to control different devices in a house such as the lights, the gate, the door of the garage and so on. Imagine to have a remote having different buttons and to be able to connect to each button a device.
Each device could work in a different way from the others, a gate opens and closes, the light turn on and off. Idea is to abstract from the specific action to be performed and having a common interface.
###Command interface
This interface must be implemented by a command object which wraps the Receiver
and collect some action over it in the execute()
method.
public interface Command {
void execute();
}
###Receiver
The light is the Receiver
of the request, it is the device produced by a specific vendor. It has a specific interface which describes, through the methods, the possible behavior of the device.
public class Light {
private boolean on;
public void on() {
on = true;
}
public void off() {
on = false;
}
}
###Concrete Command
The LightCommand
is a wrapper for the Receiver
, the device the request has to be delegated to. The method execute()
group a set of action which will be invoked over the Receiver
.
In general a command represent a specific action on a device such as turn on or turn off the light. Each command is then assign to a button on the remote.
The command object encapsulate a request of a device, it is used to make requests, each request will be delegated to the wrapped Receiver
.
This class is a command and could be implemented by the vendor with specific actions for the controlled device.
public class LightOnCommand implements Command{
Light light;
public LightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
Another command to be assigned to another button.
public class LightOffCommand implements Command{
// same code
@Override
public void execute() {
light.off();
}
}
###Invoker
The RemoteControl
class is the Invoker
which, in this case, has only one button as stated by the slot
variable, able to hold a device to control. When the Client
presses the button, the method buttonPressed()
is invoked.
The Invoker
manages the command objects, one per button. In this case there is only one button.
The client is decoupled from the specific device interface, he doesn’t have to know the details of the device that is how to turn on or of the light, he has just to press a button.
public class RemoteControl {
Command slot;
public void setCommand(Command command) {
slot = command;
}
public void buttonPressed() {
slot.execute();
}
}
Client
The client prepare the remote to be used loading command objects in the specific slots. Each command object encapsulate a request of a device.
doesn’t use the device, that is the Receviver
, directly but through the Invoker
which is the remote control.
public class Client {
public static void main(String[] args) {
// invoker
RemoteControl remoteControl = new RemoteControl();
// receiver
Light light = new Light();
// create a command and pass the receiver
Command command = new LightCommand(light);
// pass the command to the invoker
remoteControl.setCommand(command);
// press the button
remoteControl.buttonPressed();
}
}