Command Design Pattern (TAKE TWO!)
overview
DEFINITION
-
IS A BEHAVIORAL DESIGN PATTERN
-
turns a request into a stand-alone object that contains all information about the request
-
parameterize methods with different requests, delay or queue a request’s execution
-
support undoable operations
PLAIN WORDS
Allows you to encapsulate actions in objects. The key idea behind this pattern is to provide the means to decouple client from receiver.
Concept / analogy
ordering food at a restaurant:
You (i.e. Client) ask the waiter (i.e. Invoker) to bring some food (i.e. Command) and waiter simply forwards the request to Chef (i.e. Receiver) who has the knowledge of what and how to cook.
lets say We want to program a remote control api
but we have so many diff vendor classes with diff operations
The STATEMENT Problem 1
Business Logic & User Interface Layer is tightly coupled together
The STATEMENT Problem 2
Some operations may have different parameters
The STATEMENT Problem 3
Some operations can be invoked from different places
Structure explaination
The Customer
The Waiter
The Order
The Order
The Chef
with command pattern, we encapsulate each operation into a command
Device (Receiver) will react to the invoked command
Command can be assigned to a particular slot (invoker)
the remote control
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
// initialize emtpy commands in all slots
public RemoteControl() {
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
for(int i=0; i<7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].execute();
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
}
public String toString() {
// ommited the implement to print the remote control based on the configurations
}
}
THE Commands
public interface Command {
public void execute();
}
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void onButtonWasPushed(int slot) {
light.on();
}
}
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
this.light.off();
}
}
public class StereoOnWithCDCommand implements Command {
Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
public void execute() {
this.stereo.on();
this.stereo.setCD();
this.stereo.setVolume(11);
}
}
public static void main (String[] args) {
// Create all devices (Receiver) in the proper locations
Light livingRoomLight = new Light("Living Room");
Light kitchenLight = new Light("Kitchen");
CeilingFan ceilingFan = new CeilingFan("Living Room");
GarageDoor garageDoor = new GarageDoor("");
Stereo stereo = new Stereo("Living Room");
// Create all Light Commands
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
// Create all On & Off Commands for the ceiling fan
CeilingFanOnCommand ceilingFanOn = new CeilingFanOnCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
// Create all Up & Down Commands for the garage door
GarageDoorUpCommand garageDoorUp = new GarageDoorUpCommand(garageDoor);
GarageDoorDownCommand garageDoorDown = new GarageDoorDownCommand(garageDoor);
// Create all On & Off Commands for the stereo
StereoOnWithCDCommand stereOnWithCD = new StereoOnWithCDCommand(stereo);
StereoOffCommand stereOff = new StereoOffCommand(stereo);
// Load all the commands into the remote slots
RemoteControl remoteControl = new RemoteControl();
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
remoteControl.setCommand(2, ceilingFanOn, ceilingFanOff);
remoteControl.setCommand(3, stereoOnWithCD, stereoOff);
System.out.printlin(remoteControl); // print out the remote control
// press the buttons!
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(2);
remoteControl.onButtonWasPushed(3);
remoteControl.offButtonWasPushed(3);
}
THE CLIENT
Result
Application 1
WHen to use the command pattern
When you want to parametrize objects with operations.
Application 2
WHen to use the command pattern
You want to queue operations, schedule their execution or execute them remotely.
IMPLEMENTING JOB QUEUE
Application 3
WHen to use the command pattern
You want to implement reversible operations.
IMPLEMENTING UNDO
Application 4
WHen to use the command pattern
You want to implement logging of every command executions for auto failover
- Store a backup on every command execution
- Load the backup upon any server crashing to restore the state
IMPLEMENTING Auto Failover
references
Kahoot
Command Design Pattern Retake
By Wan Mohd Hafiz
Command Design Pattern Retake
- 378