Command

Chain of responsibility Computer Science Design Patterns
Command
Interpreter

The command pattern is an Object behavioural pattern that decouples sender and receiver. It can also be thought as an object oriented equivalent of call back method. Call Back: It is a function that is registered to be called at later point of time based on user actions.

Scope

Object

Purpose

Behavioral

Intent

Encapsulate the request for a service as an object.

Applicability

  • to parameterize objects with an action to perform
  • to specify, queue, and execute requests at different times
  • for a history of requests
  • for multilevel undo/redo

Structure

Command.jpg

Consequences

  • + abstracts executor of a service
  • + supports arbitrary-level undo-redo
  • + composition yields macro-commands
  • - might result in lots of trivial command subclasses

Examples

Libreoffice writer nice pic of ui.png

The best example for this pattern is the graphical user interface. On most multidata interfaces, you have both a "New" menu and a "New" button with an icon like in Libre Office Writer. The both controls are connected to a command object, so the action is performed by the same code.

Cost

This pattern is dealing with the whole architecture of your program. It can have important impacts on your project.

Creation

If the code already exists, this pattern is very expensive.

Maintenance

This pattern is very expensive to maintain.

Removal

This pattern is very expensive to remove too.

Advises

  • Use the Command term to indicate the use of the pattern to the other developers.

Implementations

Consider a "simple" switch. In this example we configure the Switch with two commands: to turn the light on and to turn the light off. A benefit of this particular implementation of the command pattern is that the switch can be used with any device, not just a light — the Switch in the following example turns a light on and off, but the Switch's constructor is able to accept any subclasses of Command for its two parameters. For example, you could configure the Switch to start an engine.

Implementation in Java
/* The Command interface */
public interface Command {
   void execute();
}
import java.util.List;
import java.util.ArrayList;
/* The Invoker class */
public class Switch {
   private List<Command> history = new ArrayList<Command>();
   public Switch() {
   }
   public void storeAndExecute(Command cmd) {
      this.history.add(cmd); // optional
      cmd.execute();        
   }
}
/* The Receiver class */
public class Light {
   public Light() {
   }
   public void turnOn() {
      System.out.println("The light is on");
   }
   public void turnOff() {
      System.out.println("The light is off");
   }
}
/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand implements Command {
   private Light theLight;
   public FlipUpCommand(Light light) {
      this.theLight = light;
   }
   public void execute(){
      theLight.turnOn();
   }
}
/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand implements Command {
   private Light theLight;
   public FlipDownCommand(Light light) {
      this.theLight = light;
   }
   public void execute() {
      theLight.turnOff();
   }
}
/* The test class or client */
public class PressSwitch {
   public static void main(String[] args){
      Light lamp = new Light();
      Command switchUp = new FlipUpCommand(lamp);
      Command switchDown = new FlipDownCommand(lamp);
      Switch s = new Switch();
      try {
         if (args[0].equalsIgnoreCase("ON")) {
            s.storeAndExecute(switchUp);
         }
         else if (args[0].equalsIgnoreCase("OFF")) {
            s.storeAndExecute(switchDown);
         }
         else {
            System.out.println("Argument \"ON\" or \"OFF\" is required.");
         }
      } catch (Exception e) {
         System.out.println("Arguments required.");
      }
   }
}

Operations

The implementations to do are:

  • copying a command before putting it on a history list
  • handling hysteresis
  • supporting transactions
  1.  public interface Command {
    
  2.    public int execute(int a, int b);
    
  3.  }
    
  1.  public class AddCommand implements Command {
    
  2.    public int execute(int a, int b) {
    
  3.       return a + b;
    
  4.    }
    
  5.  }
    
  1.  public class MultCommand implements Command {
    
  2.    public int execute(int a, int b) {
    
  3.       return a * b;
    
  4.    }
    
  5.  }
    
  1.  public class TestCommand {
    
  2.    public static void main(String a[]) {
    
  3.      Command add = new AddCommand();
    
  4.      add.execute(1, 2); // returns 3
    
  5.      Command multiply = new MultCommand();
    
  6.      multiply.execute(2, 3); // returns 6
    
  7.    }
    
  8.  }
    

In the above example, it can be noted that the command pattern decouples the object that invokes the operation from the ones having the knowledge to perform it.

Command in Java

Menus and buttons provide a classic example of the need for the Command pattern. When you add a menu to an application, you have to configure the menu with words that describe actions that the user can choose, such as Save and Open. Similarly for a button. You also have to configure the menu or button so that it can take action, calling a method in response to a user's click. However, JMenuItem or JButton class has no way of knowing what action to perform when an item or button is selected. In the following example we use the same Action for both a menu item and a button saving us from having to write the same code twice.

  1.  Action actionOpen = new AbstractAction("Open...", iconOpen) {
    
  2.       public void actionPerformed(ActionEvent e) {
    
  3.        ...    // open a file
    
  4.       }
    
  5.  }
    
  6.  
    
  7.  JMenu mFile = new JMenu("File");
    
  8.  JMenuItem item =  mFile.add(actionOpen);   // use the same action for both a menu item ...
    
  9.  
    
  10.  JToolBar m_toolBar = new JToolBar();
    
  11.  JButton bOpen = new JButton(actionOpen);   // ... and a button
    
  12.  m_toolBar.add(bOpen);
    

Java Swing applications commonly apply the Mediator pattern, registering a single object to receive all GUI events. This object mediates the interaction of the components and translates user input into commands for business domain objects.

Undo in Java

Swing provides for Undo/Redo functionality.

  1.  import javax.swing.undo.*;
    
  2.  
    
  3.  UndoManager undoManager = new UndoManager();
    
  4.  Action undoAction, redoAction;
    
  5.  undoAction = new AbstractAction("Undo",    
    
  6.      new ImageIcon("edit_undo.gif")) {
    
  7.       public void actionPerformed(ActionEvent e) {
    
  8.         try {
    
  9.           undoManager.undo(); // undoManager.redo();
    
  10.         }
    
  11.         catch (CannotUndoException ex) {
    
  12.           System.err.println("Unable to undo: " + ex);
    
  13.         }
    
  14.         updateUndo();
    
  15.       }
    
  16.     };
    
  17.  // same for Redo
    
  18.  
    
  19.  protected void updateUndo() {
    
  20.     if(undo.canUndo()) {
    
  21.       undoAction.setEnabled(true);
    
  22.       undoAction.putValue(Action.NAME, undo.getUndoPresentationName());
    
  23.     } else {
    
  24.       undoAction.setEnabled(false);
    
  25.       undoAction.putValue(Action.NAME, "Undo");
    
  26.     }
    
  27.     if(undo.canRedo()) {
    
  28.       redoAction.setEnabled(true);
    
  29.       redoAction.putValue(Action.NAME, undo.getRedoPresentationName());
    
  30.     } else {
    
  31.       redoAction.setEnabled(false);
    
  32.       redoAction.putValue(Action.NAME, "Redo");
    
  33.     }
    
  34.   }
    
Implementation in C#

The following code is an implementation of Command pattern in C#.

using System;
using System.Collections.Generic;
namespace CommandPattern
{
    public interface ICommand
    {
        void Execute();
    }
    /* The Invoker class */
    public class Switch
    {
        private List<ICommand> _commands = new List<ICommand>();
        public void StoreAndExecute(ICommand command)
        {
            _commands.Add(command);
            command.Execute();
        }
    }
    /* The Receiver class */
    public class Light
    {
        public void TurnOn()
        {
            Console.WriteLine("The light is on");
        }
        public void TurnOff()
        {
            Console.WriteLine("The light is off");
        }
    }
    /* The Command for turning on the light - ConcreteCommand #1 */
    public class FlipUpCommand : ICommand
    {
        private Light _light;
        public FlipUpCommand(Light light)
        {
            _light = light;
        }
        public void Execute()
        {
            _light.TurnOn();
        }
    }
    /* The Command for turning off the light - ConcreteCommand #2 */
    public class FlipDownCommand : ICommand
    {
        private Light _light;
        public FlipDownCommand(Light light)
        {
            _light = light;
        }
        public void Execute()
        {
            _light.TurnOff();
        }
    }
    /* The test class or client */
    internal class Program
    {
        public static void Main(string[] args)
        {
            Light lamp = new Light();
            ICommand switchUp = new FlipUpCommand(lamp);
            ICommand switchDown = new FlipDownCommand(lamp);
            Switch s = new Switch();
            string arg = args.Length > 0 ? args[0].ToUpper() : null;
            if (arg == "ON")
            {
                s.StoreAndExecute(switchUp);
            }
            else if (arg == "OFF")
            {
                s.StoreAndExecute(switchDown);
            }
            else
            {
                Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
            }
        }
    }
}
Implementation in Python

The following code is an implementation of Command pattern in Python.

class Switch(object):
    """The INVOKER class"""
    def __init__(self, flip_up_cmd, flip_down_cmd):
        self.flip_up = flip_up_cmd
        self.flip_down = flip_down_cmd
class Light(object):
    """The RECEIVER class"""
    def turn_on(self):
        print "The light is on"
    def turn_off(self):
        print "The light is off"
class LightSwitch(object):
    """The CLIENT class"""
    def __init__(self):
        lamp = Light()
        self._switch = Switch(lamp.turn_on, lamp.turn_off)
    def switch(self, cmd):
        cmd = cmd.strip().upper()
        if cmd == "ON":
            self._switch.flip_up()
        elif cmd == "OFF":
            self._switch.flip_down()
        else:
            print 'Argument "ON" or "OFF" is required.'
# Execute if this file is run as a script and not imported as a module
if __name__ == "__main__":
    light_switch = LightSwitch()
    print "Switch ON test."
    light_switch.switch("ON")
    print "Switch OFF test."
    light_switch.switch("OFF")
    print "Invalid Command test."
    light_switch.switch("****")
Implementation in Scala
/* The Command interface */
trait Command {
   def execute()
}
 
/* The Invoker class */
class Switch {
   private var history: List[Command] = Nil
 
   def storeAndExecute(cmd: Command) {
      cmd.execute()
      this.history :+= cmd
   }
}
 
/* The Receiver class */
class Light {
   def turnOn() = println("The light is on")
   def turnOff() = println("The light is off")
}
 
/* The Command for turning on the light - ConcreteCommand #1 */
class FlipUpCommand(theLight: Light) extends Command {
   def execute() = theLight.turnOn()
}
 
/* The Command for turning off the light - ConcreteCommand #2 */
class FlipDownCommand(theLight: Light) extends Command {
   def execute() = theLight.turnOff()
}
 
/* The test class or client */
object PressSwitch {
   def main(args: Array[String]) {
      val lamp = new Light()
      val switchUp = new FlipUpCommand(lamp)
      val switchDown = new FlipDownCommand(lamp)
 
      val s = new Switch()
 
      try {
         args(0).toUpperCase match {
            case "ON" => s.storeAndExecute(switchUp)
            case "OFF" => s.storeAndExecute(switchDown)
            case _ => println("Argument \"ON\" or \"OFF\" is required.")
         }
      } catch {
         case e: Exception => println("Arguments required.")
      }
   }
}
Implementation in JavaScript

The following code is an implementation of Command pattern in Javascript.

/* The Invoker function */
var Switch = function(){
    this.storeAndExecute = function(command){
        command.execute();
    }
}
/* The Receiver function */
var Light = function(){
    this.turnOn = function(){ console.log ('turn on')};
    this.turnOff = function(){ console.log ('turn off') };
}
/* The Command for turning on the light - ConcreteCommand #1 */
var FlipUpCommand = function(light){
    this.execute = light.turnOn;
}
/* The Command for turning off the light - ConcreteCommand #2 */
var FlipDownCommand = function(light){
    this.execute = light.turnOff;
}
var light = new Light();
var switchUp = new FlipUpCommand(light);
var switchDown = new FlipDownCommand(light);
var s = new Switch();
s.storeAndExecute(switchUp);
s.storeAndExecute(switchDown);
Implementation in Smalltalk
Object subclass: #Switch
  instanceVariableNames:
    ' flipUpCommand flipDownCommand '
  classVariableNames: ''
  poolDictionaries: ''
 
Object subclass: #Light
  instanceVariableNames: ''
  classVariableNames: ''
  poolDictionaries: ''
 
Object subclass: #PressSwitch
  instanceVariableNames: ''
  classVariableNames: ''
  poolDictionaries: ''
 
!Switch class methods !
upMessage: flipUpMessage downMessage: flipDownMessage
^self new upMessage: flipUpMessage downMessage: flipDownMessage; yourself.! !
!Switch methods !
upMessage: flipUpMessage downMessage: flipDownMessage
flipUpCommand := flipUpMessage.
flipDownCommand := flipDownMessage.!
flipDown
flipDownCommand perform.!
 
flipUp
flipUpCommand perform.! !
 
!Light methods !
turnOff
Transcript show: 'The light is off'; cr.!
 
turnOn
Transcript show: 'The light is on'; cr.! !
!PressSwitch class methods !
switch: state
" This is the test method "
| lamp switchUp switchDown switch |
lamp := Light new.
switchUp := Message receiver: lamp selector: #turnOn.
switchDown := Message receiver: lamp selector: #turnOff.
switch := Switch upMessage: switchUp downMessage: switchDown.
state = #on ifTrue: [ ^switch flipUp ].
state = #off ifTrue: [ ^switch flipDown ].
Transcript show: 'Argument #on or #off is required.'.
! !


Clipboard

To do:
Add more illustrations.


Chain of responsibility Computer Science Design Patterns
Command
Interpreter


You have questions about this page?
Ask it here:


Create a new page on this book:

Last modified on 29 January 2014, at 06:43