It is another data-driven
pattern. The client invokes a particular module using a command or an Action (Basically
calling a method).Command Pattern allows you to decouple the requester of an
action from object that actually performs the action by introducing command
objects.
Definition:
Definition:
“Encapsulate a request
as an object, thereby letting you parameterize clients with different requests,
queue or log requests, and support undoable operations.”
Head First Java
Command
Pattern at First Glance:
I will be a bit
violent here but this is the best example I could ever think of after reading a
lot of content on Command Design Pattern. Let us assume we are living in Germany
in the times of Second World War. He is our commanding officer, and at his one command
Military, Air Force and Navy would start firing.
Hitler the Commanding Officer |
Let us have a look at the Command Pattern from the flow perspective.
Object Creation and Flow |
Class
Diagram
Before making our hand dirty just let us have a glance at the
Structure of Command Pattern.
Class Diagram |
Do not bother about this class diagram right away; I am sure we
will understand it after we see the coding. We will be relating our code with
the Class diagram
Let
us try out Some Coding
We have two interfaces Command and Soldier (Receiver).
public interface Command {
// Relate this as Execute method in the Class diagram
void executeFire();
// Relate this to UNDO action
void executeStopFire();
// Other Actions can also be declared
void executeHoldBack();
}
public interface Soldier {
// Various Action to be performed by the Receiver on getting command
void fire();
void stopFire();
void holdBack();
}
|
Let us create some concrete Receivers of the
Commands
public class ArmySoldier implements Soldier{
@Override
public void fire() {
System.out.println("Army
is Firing");
}
@Override
public void holdBack() {
System.out.println("Army
is on Hold Back");
}
@Override
public void stopFire() {
System.out.println("Army
has Stopped Firing");
}
}
public class AirForceSoldier implements Soldier{
@Override
public void fire() {
System.out.println("Air
Force is Firing");
}
@Override
public void holdBack() {
System.out.println("Air
Force is on Hold Back");
}
@Override
public void stopFire() {
System.out.println("Air
Force has Stopped Firing");
}
}
public class NavySoldier implements Soldier{
@Override
public void fire() {
System.out.println("Navy
is Firing");
}
@Override
public void holdBack() {
System.out.println("Navy
is on Hold Back");
}
@Override
public void stopFire() {
System.out.println("Navy
has Stopped Firing");
}
}
|
Let us create some concrete Commands
public class ArmySoldierCommand implements Command{
Soldier armySoldier;
public ArmySoldierCommand(Soldier armySoldier) {
this.armySoldier = armySoldier;
}
@Override
public void executeFire() {
armySoldier.fire();
}
@Override
public void executeHoldBack() {
armySoldier.holdBack();
}
@Override
public void executeStopFire() {
armySoldier.stopFire();
}
}
public class AirForceSoilderCommand implements Command{
Soldier airForceSoldier;
public AirForceSoilderCommand(Soldier
airForceSoldier) {
this.airForceSoldier = airForceSoldier;
}
@Override
public void executeFire() {
airForceSoldier.fire();
}
@Override
public void executeHoldBack() {
airForceSoldier.holdBack();
}
@Override
public void executeStopFire() {
airForceSoldier.stopFire();
}
}
public class NavySoilderCommand implements Command{
Soldier navySoldier;
public NavySoilderCommand(Soldier navySoldier) {
this.navySoldier = navySoldier;
}
@Override
public void executeFire() {
navySoldier.fire();
}
@Override
public void executeHoldBack() {
navySoldier.holdBack();
}
@Override
public void executeStopFire() {
navySoldier.stopFire();
}
}
|
Now the most Important class the INVOKER ADOLF HITLER
public class Hitler {
static List
public static void
addCommand(Command command){
commandList.add(command);
}
public static void
executeFireCommand(Command command){
command.executeFire();
}
public static void
executeStopFireCommand(Command command){
command.executeStopFire();
}
public static void executeHoldBackCommand(Command
command){
command.executeHoldBack();
}
public static void
executeFireAllCommands(){
Iterator
while (iterator.hasNext()) {
Command command
= (Command) iterator.next();
command.executeFire();
}
}
// Similarly you can have other methods as per your requirement
}
|
Let us test use Command Loader (Client) to test our Command
Pattern
public class CommandLoader {
public static void
main(String[] args) {
// Initialising the Soldiers (They are the reciever's of the command)
Soldier armySoldier = new ArmySoldier();
Soldier airForceSoldier = new AirForceSoldier();
Soldier navySoldier = new NavySoldier();
// Initialising the Concrete Commands
Command armyCommand = new ArmySoldierCommand(armySoldier);
Command airForceCommand = new
AirForceSoilderCommand(airForceSoldier);
Command navyCommand = new NavySoilderCommand(navySoldier);
System.out.println("Hitler
Executes Individual Fire Commands");
Hitler.executeFireCommand(armyCommand);
Hitler.executeFireCommand(airForceCommand);
Hitler.executeFireCommand(navyCommand);
System.out.println("Hitler
Executes Individual Stop Fire Commands");
// Hitler can command his forces as per the plan
Hitler.executeStopFireCommand(armyCommand);
Hitler.executeHoldBackCommand(armyCommand);
System.out.println("Hitler
Executes All Fire Commands");
// Here we load all commands to execute all in a Single shot
Hitler.addCommand(armyCommand);
Hitler.addCommand(airForceCommand);
Hitler.addCommand(navyCommand);
Hitler.executeFireAllCommands();
}
}
OUTPUT is as Follows: All this is simple to understand
Hitler Executes Individual Fire Commands
Army is Firing
Air Force is Firing
Navy is Firing
Hitler Executes Individual Stop Fire Commands
Army has Stopped Firing
Army is on Hold Back
Hitler Executes All Fire Commands
Army is Firing
Air Force is Firing
Navy is Firing
|
By this time we all have understood Command Patterns very well,
not is time to relate our classes to the class diagram
One last thing is left
to be discussed is UNDO action i.e. to stop the command fire or reverse the
state of the command (Think of it like another command). In our example we have
already covered it. It’s just that we haven’t yet realized it, for those who
are JAVA geeks might have already felt the stopFireCommand() is our undo
command. We can have multiple such actions as per our needs.
Real Time Scenarios to Use Command
Pattern:
- This pattern works very well in GUI code (Action Listeners), but it can be applied wherever it is possible and worthwhile to make operations reversible.
- Commands may also be used to logging,queuing requests and transactional systems.
- Menu Actions like Cut, Copy and Paste uses Command Pattern
- It is also possible for a command to be a collection of commands, called a Macro Command. Macro Commands are simple extension of Command that allow multiple commands to be invoked and they can easily support undo operations.
- It may lead to a little explosion of classes
Your examples are too good man...You explained one of the most confusing GoF design pattern with ease...hats off :)
ReplyDeleteHey Thanks Abhi.....Dude this can't be confusing for you....GUI champ....I try to keep my examples as simple as Possible...
ReplyDeleteThank you for posting! Just a suggestion: since the different Command(s) delegate on the concrete Soldier implementations through its interface, it seems there should be only one concrete Command (all of them do the same thing). I think it would be better if you include some specific behaviour in the concrete implementations of the Command interface.
ReplyDeleteCheers!
Dude,
ReplyDeleteVery bad example. There is no UNDO action to firing missiles or killing people.
I guess people are more hurt by this example...its a bit violent.... Apologies for that..
ReplyDeleteYou are correct in stating that there is no UNDO action if a gun is fired...Here i didn't wanted to reverse the action we fired but only to stop it....
We can anyways relate to UNDO actions with some other examples....
Seriously, worst theme ever used for a coding example!
ReplyDelete