25% developed

Command

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Chain of responsibility Computer Science Design Patterns
Command
Composite

The command pattern is an object behavioural pattern that decouples sender and receiver. It can also be thought as an object-oriented equivalent of a call back method. Call back: It is a function that is registered to be called at a 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

UML diagram of the command pattern
UML diagram of the command pattern

Consequences

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

Examples

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. 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 a program. It may have a substantial impact on the 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){
      // Check number of arguments
      if (args.length != 1) {
         System.err.println("Argument \"ON\" or \"OFF\" is required.");
         System.exit(-1);
      }

      Light lamp = new Light();
      Command switchUp = new FlipUpCommand(lamp);
      Command switchDown = new FlipDownCommand(lamp);

      // See criticism of this model above:
      // The switch itself should not be aware of lamp details (switchUp, switchDown)
      // either directly or indirectly
      Switch mySwitch = new Switch();

      switch (args[0]) {
         case "ON":
            mySwitch.storeAndExecute(switchUp);
            break;
         case "OFF":
            mySwitch.storeAndExecute(switchDown);
            break;
         default:
            System.err.println("Argument \"ON\" or \"OFF\" is required.");
            System.exit(-1);
        }
   }
}

Operations

The implementations to do are:

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

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.

 Action actionOpen = new AbstractAction("Open...", iconOpen) {
      public void actionPerformed(ActionEvent e) {
       ...    // open a file
      }
 }
 
 JMenu mFile = new JMenu("File");
 JMenuItem item =  mFile.add(actionOpen);   // use the same action for both a menu item ...
 
 JToolBar m_toolBar = new JToolBar();
 JButton bOpen = new JButton(actionOpen);   // ... and a button
 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.

 import javax.swing.undo.*;
 
 UndoManager undoManager = new UndoManager();
 Action undoAction, redoAction;
 undoAction = new AbstractAction("Undo",    
     new ImageIcon("edit_undo.gif")) {
      public void actionPerformed(ActionEvent e) {
        try {
          undoManager.undo(); // undoManager.redo();
        }
        catch (CannotUndoException ex) {
          System.err.println("Unable to undo: " + ex);
        }
        updateUndo();
      }
    };
 // same for Redo
 
 protected void updateUndo() {
    if(undo.canUndo()) {
      undoAction.setEnabled(true);
      undoAction.putValue(Action.NAME, undo.getUndoPresentationName());
    } else {
      undoAction.setEnabled(false);
      undoAction.putValue(Action.NAME, "Undo");
    }
    if(undo.canRedo()) {
      redoAction.setEnabled(true);
      redoAction.putValue(Action.NAME, undo.getRedoPresentationName());
    } else {
      redoAction.setEnabled(false);
      redoAction.putValue(Action.NAME, "Redo");
    }
  }
Implementation in C#

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 C# implementation 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.

using System;

namespace CommandPattern;

public interface ICommand
{
    void Execute();
}

/* The Invoker class */
public class Switch
{
    ICommand _closedCommand;
    ICommand _openedCommand;

    public Switch(ICommand closedCommand, ICommand openedCommand)
    {
        _closedCommand = closedCommand;
        _openedCommand = openedCommand;
    }

    // Close the circuit / power on
    public void Close()
    {
       _closedCommand.Execute();
    }

    // Open the circuit / power off
    public void Open()
    {
        _openedCommand.Execute();
    }
}

/* An interface that defines actions that the receiver can perform */
public interface ISwitchable
{
    void PowerOn();
    void PowerOff();
}

/* The Receiver class */
public class Light : ISwitchable
{
    public void PowerOn()
    {
        Console.WriteLine("The light is on");
    }

    public void PowerOff()
    {
        Console.WriteLine("The light is off");
    }
}

/* The Command for turning off the device - ConcreteCommand #1 */
public class CloseSwitchCommand : ICommand
{
    private ISwitchable _switchable;

    public CloseSwitchCommand(ISwitchable switchable)
    {
        _switchable = switchable;
    }

    public void Execute()
    {
        _switchable.PowerOff();
    }
}

/* The Command for turning on the device - ConcreteCommand #2 */
public class OpenSwitchCommand : ICommand
{
    private ISwitchable _switchable;

    public OpenSwitchCommand(ISwitchable switchable)
    {
        _switchable = switchable;
    }

    public void Execute()
    {
        _switchable.PowerOn();
    }
}

/* The test class or client */
internal class Program
{
    public static void Main(string[] arguments)
    {
        string argument = arguments.Length > 0 ? arguments[0].ToUpper() : null;

        ISwitchable lamp = new Light();

        // Pass reference to the lamp instance to each command
        ICommand switchClose = new CloseSwitchCommand(lamp);
        ICommand switchOpen = new OpenSwitchCommand(lamp);

        // Pass reference to instances of the Command objects to the switch
        Switch @switch = new Switch(switchClose, switchOpen);

        if (argument == "ON")
        {
            // Switch (the Invoker) will invoke Execute() on the command object.
            @switch.Open();
        }
        else if (argument == "OFF")
        {
            // Switch (the Invoker) will invoke the Execute() on the command object.
            @switch.Close();
        }
        else
        {
            Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
        }
    }
}

The following code is another 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.'.
! !
Implementation in PHP

The following code is an implementation of command pattern in PHP.

<?php

interface Command
{

    public function execute();
}

/** The Invoker class */
class Switcher
{

    private $history = array();

    public function storeAndExecute(Command $cmd)
    {
        $this->history[] = $cmd;
        $cmd->execute();
    }

}

/** The Receiver class */
class Light
{

    public function turnOn()
    {
        echo("The light is on");
    }

    public function turnOff()
    {
        echo("The light is off");
    }

}

/** The Command for turning on the light - ConcreteCommand #1 */
 class FlipUpCommand implements Command {
   private $theLight;

   public function __construct(Light $light) {
      $this->theLight = $light;
   }

   public function execute() {
       $this->theLight->turnOn();
   }
}

/** The Command for turning off the light - ConcreteCommand #2 */
 class FlipDownCommand implements Command {
   private $theLight;

   public function __construct(Light $light) {
      $this->theLight = $light;
   }

   public function execute() {
       $this->theLight->turnOff();
   }
}

/* The test class or client */
 class PressSwitch {
   public static  function main(string $args){

      $lamp = new Light();
      $switchUp = new FlipUpCommand($lamp);
      $switchDown = new FlipDownCommand($lamp);

      $mySwitch = new Switcher();

      switch($args) {
         case 'ON':
            $mySwitch->storeAndExecute($switchUp);
            break;
         case 'OFF':
            $mySwitch->storeAndExecute($switchDown);
            break;
         default:
            echo("Argument \"ON\" or \"OFF\" is required.");
            break;
      }
   }
}

/*INPUT*/

PressSwitch::main('ON'). PHP_EOL;
PressSwitch::main('OFF'). PHP_EOL;

/*OUTPUT*/
//The light is on
//The light is off


Chain of responsibility Computer Science Design Patterns
Command
Composite


You have questions about this page?
Ask it here:


Create a new page on this book: