In the series of behavioral design patterns, the Command Pattern is the one that encapsulates method invocation. We can issue requests to objects without knowing anything about the operation being requested or the receiver of the request. Let’s go into detail and see what it is:

The Command Pattern

The Command Pattern encapsulates a request as an object, thereby letting you parameterize clients with various requests, queue or log requests, and support undoable operations. (Gamma et. al.).

Uses of The Command Pattern

Let’s understand it with an example of the use of the Command Pattern.

I will use the same example I did in my first blog; The Remote Control. A company that manufactures the remote control, has several vendors (classes). These vendors have their own set of methods and interfaces to be invoked, such as On, Off, Dim, IncreaseVolumne, DecreaseVolume and so on and so forth. There are not many common interfaces among several vendor classes other than ON or OFF.

The manufacturing company can expect more diverse classes in the future with just as diverse methods. A bad design for the problem would be:

If(slot1== TV), then light.On(),

else if(slot1==Washmachine), then washmachine.On()


One way of analyzing the preceding problem is to follow the Separation of Concerns Principle: The remote should know how to interpret button presses and make requests, but it should not know a lot about home automation.

Goals of a good design for this situation:

UML Diagram and participants:

Command pattern

For the sake of a better understanding, I have mapped participants in the pattern with probable classes in my example.

Participants

The classes and/or objects participating in this pattern are:

Sequence Diagram

A Sequence Diagram shows how multiple participants communicates among each other.

design

Step-by-step analysis:

  1. The client creates a ConcreteCommand object and specifies its receiver.

  2. An invoker object stores the concreteCommand object.

  3. The Invoker issues a request by calling Execute on the command. When commands are undoable, ConcreteCommand stores for undoing the command prior to invoking Execute.

  4. The concreteCommand object invokes operations on its receiver to carry out the request.

As it is said, if you are able to execute an action, you should also know how to undo the executed action. The same applies to our example too. If a household is started, the undo button should be able to shut it down. Or let’s say any last executed action should be reset when the undo button is pressed.

How to undo it

Command Pattern in action

Abstract Command class:

  1. public abstract class ICommand
  2. {
  3. public abstract void Exceute();
  4. public abstract void Undo();
  5. }
Concrete Receivers

An Oven and Washing machine are receivers in our examples. They only know how can they be switched on or switched off.

Oven
  1. public class Oven
  2. {
  3. internal void SwitchOff()
  4. {
  5. MessageBox.Show("Oven is off");
  6. }
  7. internal void SwitchOn()
  8. {
  9. MessageBox.Show("Oven is on");
  10. }
  11. }
  12. //Washmachine
  13. public class Waschmachine
  14. {
  15. internal void SwitchOn()
  16. {
  17. MessageBox.Show("Switching On Washing Machine");
  18. }
  19. internal void SwitchOff()
  20. {
  21. MessageBox.Show("Switching Off Washing Machine");
  22. }
  23. }
Concrete Commands

Concrete commands implement abstract command interfaces. The Execute method in a concrete class encapsulates method invocation (_waschmachine.SwitchOn()). Concrete commands also know their receivers.
  1. public class SwitchOnWaschmachine:ICommand
  2. {
  3. private readonly Waschmachine _waschmachine;
  4. public SwitchOnWaschmachine(Waschmachine waschmachine)
  5. {
  6. _waschmachine = waschmachine;
  7. }
  8. public override void Exceute()
  9. {
  10. _waschmachine.SwitchOn();
  11. }
  12. public override void Undo()
  13. {
  14. _waschmachine.SwitchOff();
  15. }
  16. public override string ToString()
  17. {
  18. return "Washing Machine";
  19. }
  20. }
Also, observe that each concrete command knows how to undo its original operation. One command knows how to switch it off and vice versa.
  1. public class SwitchOffWaschmachine :ICommand
  2. {
  3. private readonly Waschmachine _waschmachine;
  4. public SwitchOffWaschmachine(Waschmachine waschmachine)
  5. {
  6. _waschmachine = waschmachine;
  7. }
  8. public override void Exceute()
  9. {
  10. _waschmachine.SwitchOff();
  11. }
  12. public override void Undo()
  13. {
  14. _waschmachine.SwitchOn();
  15. }
  16. public override string ToString()
  17. {
  18. return "Washing Machine";
  19. }
  20. }
Invoker

A remote plays the role of an invoker and only knows how to execute a command but it does not know who the receiver of the command is and how the command is actually executed. In that way, the receiver and invoker are separated from each other.

Switch On click button
  1. private void SwitchOn_Click(object sender, EventArgs e)
  2. {
  3. Button btn = sender as Button;
  4. int col = btn != null ? Grid.GetColumn(btn) : -1;
  5. if (col == 1)
  6. {
  7. var slot = btn != null ? Grid.GetRow(btn) : -1;
  8. _onCommands[slot].Exceute(); // Execute Command
  9. _unDoCommand = _onCommands[slot];
  10. }
  11. }
Switch Off click button
  1. private void SwitchOff_Click(object sender, EventArgs e)
  2. {
  3. Button btn = sender as Button;
  4. int col = btn != null ? Grid.GetColumn(btn) : -1;
  5. if (col == 2)
  6. {
  7. var slot = btn != null ? Grid.GetRow(btn) : -1;
  8. _offCommands[slot].Exceute();
  9. _unDoCommand = _offCommands[slot];
  10. }
  11. }
Client

The client is the one that associates a concrete command with its concrete receiver and also assigns each slot in the remote a command.
  1. MainWindow remotecontrol = new MainWindow();
  2. Waschmachine waschmachine= new Waschmachine();
  3. Oven oven= new Oven();
  4. SwitchOffOven switchOffOven= new SwitchOffOven(oven);
  5. SwitchOnOven switchOnOven= new SwitchOnOven(oven);
  6. SwitchOnWaschmachine switchOnWaschmachine= new SwitchOnWaschmachine(waschmachine);
  7. SwitchOffWaschmachine switchOffWaschmachine= new SwitchOffWaschmachine(waschmachine);
  8. remotecontrol.SetCommand(0, switchOnOven, switchOffOven);
  9. remotecontrol.SetCommand(1, switchOnWaschmachine, switchOffWaschmachine);
Macro Commands

Many of us have certainly used macros in Excel. Macros are quite useful when you want to execute a series of commands every now and then. The only point to remember is that this macro (series of commands) must be stored somewhere.

In our example too, a remote control with macro commands can play a vital role to attract customers. For example, let’s say we need a button/mode on our remote. With this button, the user can configure much of the equipment all together. Let’s call this mode, the party mode. When party mode is selected, the remote should dim the lights, play the CD player, set the volume and so on. Fundamentally, the remote must know which commands to executes and in which order. That’s where Macro Commands are relevant.

Let’s see an example as in the following:
  1. //Receivers
  2. Light light= new Light();
  3. TV tv= new TV();
  4. --------
  5. //setting concrete commands and it‘s receivers
  6. LightOnCommand lightOn= new LightOnCommand(light);
  7. TVOnCommand TVOn= new TVOnCommand(Tv);
  8. ------
  9. //command collection both on and off
  10. Command[] partyOn={lightOn, TVOn,…..};
  11. Command[] partyOff={lightOff,TV TVOff,…..};
  12. //set macro commands that accepts a collection of commands
  13. MacroCommand partyOnMacro= new MacroCommand(partyOn);
  14. MacroCommand partyOffMacro= new MacroCommand(partyOff);
  15. //assign macro command to button on remote control
  16. remoteControl.SetCommand(7, partyOnMacro,partyOffMacro);
  17. -------
  18. // Playiton
  19. remoteControl.SwitchOn();
  20. -----
  21. //switchitOff
  22. remoteControl.SwitchOff();
Macro Commands

Other usages of command

Advantages and Disadvantages