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 (TAKE TWO!)
Command Design Pattern Retake
By Wan Mohd Hafiz
Command Design Pattern Retake
- 446