SDSU Advanced Object-Oriented Design & Programming
Spring Semester, 2005
Previous     Lecture Notes Index     Next     
© 2005 All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated March 10, 2005

Doc 12 Command




When to Use the Command Pattern    


Command Processor    






Copyright ©, All rights reserved. 2005 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA. OpenContent ( license defines the copyright on this document.






Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison-Wesley, 1995, pp. 233-242


The Design Patterns Smalltalk Companion, Alpert, Brown, Woolf, Addision-Wesley, 1998, pp. 245-260


Pattern-Oriented Software Architecture: A System of Patterns, Buschman, Meunier, Rohnert, Sommerlad, Stal, 1996, pp. 277-290, Command Processor


Command Processor, Sommerlad in Pattern Languages of Program Design 2, Eds. Vlissides, Coplien, Kerth, Addison-Wesley, 1996, pp. 63-74


Advanced C++: Programming Styles and Idioms, James Coplien,  Addison Wesley, 1992, pp 165-170, Functor Pattern





Encapsulates a request as an object








Invoker be a menu

Client be a word processing program

Receiver a document

Action be save




When to Use the Command Pattern


  1. When you need an action as a parameter

Commands replace callback functions


  1. When you need to specify, queue, and execute requests at different times


  1. When you need to support undo


  1. When you need to support logging changes


  1. When you structure a system around high-level operations built on primitive operations


A Transactions encapsulates a set of changes to data


Systems that use transaction often can use the command pattern


  1. When you need to support a macro language






Command decouples the object that invokes the operation from the one that knows how to perform it


It is easy to add new commands, because you do not have to change existing classes


You can assemble commands into a composite object




Example - Menu Callbacks


abstract class Command


    abstract public void execute();



class OpenCommand extends Command


    private Application opener;


    public OpenCommand( Application theOpener )


        opener = theOpener;



    public void execute()


        String documentName = AskUserSomeHow();


        if ( name != null )


            Document toOpen =

                    new Document( documentName );

            opener.add( toOpen );






Using Command


class Menu


    private Hashtable menuActions = new Hashtable();


    public void addMenuItem( String displayString,

                        Command itemAction )


        menuActions.put( displayString, itemAction );



    public void handleEvent( String itemSelected )


        Command runMe;

        runMe = (Command) menuActions.get( itemSelected );




    // lots of stuff missing








class MacroCommand extends Command {

    private Vector commands = new Vector();


    public void add( Command toAdd ) {

        commands.addElement( toAdd );



    public void remove( Command toRemove ) {

        commands.removeElement( toAdd );



    public void execute() {

        Enumeration commandList = commands.elements();


        while ( commandList.hasMoreElements() )


            Command nextCommand;

            nextCommand = (Command)











Prevalence layer for Java


Database that

  1. Serializes object to save them to disk

  1. Uses commands when modifying objects

  1. Keeps log of commands




Restaurant Example


import java.util.*;

import org.prevayler.implementation.AbstractPrevalentSystem;


public class Restaurant extends AbstractPrevalentSystem {

    private String name;

    ArrayList ratings = new ArrayList();


    public Restaurant(String newName) { name = newName;}


    public String name() {return name;}


    public void addRating( int newRating) {

        ratings.add( new Integer(newRating));



    public float getRating() {

        if (ratings.size() == 0 )

            return -1;

        int total = 0;

        for (int k =0; k < ratings.size();k++)

            total = total + ((Integer)ratings.get(k)).intValue();

        return total/ ratings.size();









import org.prevayler.Command;

import org.prevayler.PrevalentSystem;



public class AddRatingCommand implements Command {

    private final int newRating;


    public AddRatingCommand(int rating) {

        newRating = rating;



    public Serializable execute(PrevalentSystem system) {


        return null;






First Run


import java.util.*;

import org.prevayler.implementation.SnapshotPrevayler;


public class PrevaylerExample {


    public static void main (String args[]) throws Exception {

        SnapshotPrevayler samsDinerData =

            new SnapshotPrevayler(new Restaurant("Sams Diner"), "food");


        System.out.println( “Start”);

        Restaurant samsDiner = (Restaurant) samsDinerData.system();

        System.out.println( samsDiner.getRating() );

        samsDinerData.executeCommand( new AddRatingCommand( 5));

        System.out.println( samsDiner.getRating() );






Recovering system state...






Second Run


public class PrevaylerExample {


    public static void main (String args[]) throws Exception {

        SnapshotPrevayler samsDinerData =

            new SnapshotPrevayler(new Restaurant("Sams Diner"), "food");


        System.out.println( “Start”);

        Restaurant samsDiner = (Restaurant) samsDinerData.system();

        System.out.println( samsDiner.getRating() );

        samsDinerData.executeCommand( new AddRatingCommand( 10));

        System.out.println( samsDiner.getRating() );






Recovering system state...

Reading food/000000000000000000001.commandLog...







Pluggable Commands


Can create one general Command using reflection


Don’t hard code the method called in the command


Pass the method to call an argument




Java Example of Pluggable Command


import java.util.*;

import java.lang.reflect.*;


public class Command


    private Object receiver;

    private Method command;

    private Object[] arguments;


    public Command(Object receiver, Method command,

                                    Object[] arguments )


        this.receiver = receiver;

        this.command = command;

        this.arguments = arguments;



    public void execute() throws InvocationTargetException,



        command.invoke( receiver, arguments );






Using the Pluggable Command


One does have to be careful with the primitive types


public class Test {

    public static void main(String[] args) throws Exception


        Vector sample = new Vector();

        Class[] argumentTypes = { Object.class };

        Method add =

            Vector.class.getMethod( "addElement", argumentTypes);

        Object[] arguments = { "cat" };


        Command test = new Command(sample, add, arguments );


        System.out.println( sample.elementAt( 0));









Pluggable Command Smalltalk Version


Object subclass: #PluggableCommand

    instanceVariableNames: 'receiver selector arguments '

    classVariableNames: ''

    poolDictionaries: ''

    category: 'Whitney-Examples'


Class Methods

receiver: anObject selector: aSymbol arguments: anArrayOrNil

    ^super new

        setReceiver: anObject

        selector: aSymbol

        arguments: anArrayOrNil


Instance Methods    

setReceiver: anObject selector: aSymbol arguments: anArrayOrNil

    receiver := anObject.

    selector := aSymbol.

    arguments := anArrayOrNil isNil

                    ifTrue:[#( )]

                    ifFalse: [anArrayOrNil]




        perform: selector

        withArguments: arguments



Using the Pluggable Command


| sample command |

sample := OrderedCollection new.

command := PluggableCommand

        receiver: sample

        selector: #add:

        arguments: #( 5 ).

command execute.

^sample at: 1




Command Processor


Command Processor manages the command objects



The command processor:


  1. Contains all command objects


  1. Schedules the execution of commands


  1. May store the commands for later unto


  1. May log the sequence of commands for testing purposes


  1. Uses singleton to insure only one instance
















  1. Flexibility in the way requests are activated


Different user interface elements can generate the same kind of command object


Allows the user to configure commands performed by a user interface element


  1. Flexibility in the number and functionality of requests


Adding new commands and providing for a macro language comes easy


  1. Programming execution-related services


Commands can be stored for later replay

Commands can be logged

Commands can be rolled back


  1. Testability at application level


  1. Concurrency


Allows for the execution of commands in separate threads







  1. Efficiency loss


  1. Potential for an excessive number of command classes


Try reducing the number of command classes by:


Grouping commands around abstractions


Unifying simple commands classes by passing the receiver object as a parameter



  1. Complexity


How do commands get additional parameters they need?





Functions as Objects


A functor is a class with


  1. A single member function (method)



Functors are functions that behave like objects


They serve the role of a function, but can be created, passed as parameters, and manipulated like objects


final class StudentNameComparator implements Comparator {


   public int compare( Object leftOp, Object rightOp ) {

      String leftName = ((Student) leftOp).name;

      String rightName = ((Student) rightOp).name;

      return leftName.compareTo( rightName );







How Does a Functor Compare to Function Pointers?


  1. Using inheritance we can factor common code to a base class

  1. Same run-time flexibility as function pointer

  1. Lends it self to poor abstractions


How does A Functor compare with Command?




When to use the Functor


Coplien states:


Use functors when you would be tempted to use function pointers


Functors are commonly used for callbacks

Previous     visitors since March 10, 2005     Next