SDSU CS 696: Advanced OO
Spring Semester, 1997
Doc 15, Functors, Command, Template Mehod

To Lecture Notes Index
San Diego State University -- This page last updated Apr 15, 1997
----------

Contents of Doc 15, Functors, Command, Template Mehod


Functor slide # 1
Command slide # 6
Template Method slide # 10

References

Design Patterns: Elements of Resuable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison-Wesley, 1995

Advanced C++: Programing Styles and Idioms, James Coplien, Addison Wesley, 1992


Doc 15, Functors, Command, Template Mehod Slide # 1

Functor

Functions as Objects

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

A functor is a class with a single member function


Example - Sorting

class SortedList
     {
     private Object[] listElements;
     
     private void sortTheList()
          {
          // use fancy sort method like quicksort
          blah
          blah
          
          if ( listElement[k] > listElement[k+j] )
               {
               swap or something
               }
          }
     }



Doc 15, Functors, Command, Template Mehod Slide # 2
How do we compare Elements?

We don't know the type?

We may wish to sort the same objects in different ways

by name
by id
by address
In C++ we could use function pointers, but not in Java


Functor Solution

abstract class Compare
     {
     private static final int LESS_THAN = -1;
     private static final int GREATER_THAN = 1;
     private static final int EQUAL_TO = 0;
     
     public boolean greaterThan( Object a, Object b )
          {
          int result = compareTo( a, b );
          if ( result == GREATER_THAN ) return true;
          else return false;

     public boolean lessThan( Object a, Object b )
          {
          int result = compareTo( a, b );
          if ( result == LESS_THAN ) return true;
          else return false;
          }

Doc 15, Functors, Command, Template Mehod Slide # 3

public boolean equals( Object a, Object b )
          {
          int result = compareTo(a,  b );
          if ( result == EQUAL_TO ) return true;
          else return false;
          }

     abstract public int compareTo( Object a, Object b );
     }
     
class CompareInt extends Compare
     {
     public int compareTo( Object a, Object b )
          {
          if ( (int) a < (int) b )
               return LESS_THAN;
          else if  ( (int) a > (int) b )
               return GREATER_THAN;
          else
               return EQUAL_TO;
          }
     }

class CompareString extends Compare
     { blah }

class CompareStudentRecordByID extends Compare
     { blah }

class CompareStudentRecordByAddress extends Compare
     { blah }


Doc 15, Functors, Command, Template Mehod Slide # 4
class SortedList
     {
     private Object[] listElements;
     private Compare comparer;
     
     public SortedList( Compare function )
          {
          comparer = function;
          }
          
     private void sortTheList()
          {
          // use fancy sort method like quicksort
          blah
          blah
          
          if ( comparer.lessThan(listElement[k], listElement[k+j] ) )
               {
               swap or something
               }
          }
     }


Doc 15, Functors, Command, Template Mehod Slide # 5
How Does a Functor Compare to Function Pointers?

Using inheritance we can factor common code to a base class

Same run-time flexibility as function pointer

Lends it self to poor abstractions

Other?


Doc 15, Functors, Command, Template Mehod Slide # 6

Command


Maintains a binding between a receiver and a function

Give much more power than functor

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 );
               opener.open();
               }
          }
     }

Doc 15, Functors, Command, Template Mehod Slide # 7
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 );
          runMe.execute();
          }

     // lots of stuff missing
     }


Doc 15, Functors, Command, Template Mehod Slide # 8
MacroCommand

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) commandList.nextElement();
               nextCommand.execute();
               }
          }
     }


Doc 15, Functors, Command, Template Mehod Slide # 9
When to Use the Command Pattern

When you need an action as a parameter

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

When you need to support undo

When you need to support logging changes

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


Doc 15, Functors, Command, Template Mehod Slide # 10

Template Method

Polymorphism

class Account {
     public:     
          void virtual Transaction(float amount) 
                    { balance += amount;}
          Account(char* customerName, float InitialDeposit = 0);
     protected:
          char* name;
          float balance;
}

class JuniorAccount : public Account {
     public:     void Transaction(float amount) {//  put code here}
}

class SavingsAccount : public Account {
     public:     void Transaction(float amount) {//  put code here}
}

Account* createNewAccount()
{
     // code to query customer and determine what type of
     // account to create
};

main()
{
     Account*  customer;
     customer = createNewAccount();
     customer->Transaction(amount);

}
Doc 15, Functors, Command, Template Mehod Slide # 11
Deferred Methods




class Account {
     public:
          void virtual Transaction() = 0;
}

class JuniorAccount : public Account {
     public
          void Transaction() { put code here}
}

Doc 15, Functors, Command, Template Mehod Slide # 12
Template Methods

class Account {
     public:     
          void Transaction(float amount);
          void virtual TransactionSubpartA();
          void virtual TransactionSubpartB();
          void virtual TransactionSubpartC();
}

void Account::Transaction(float amount)  {
     TransactionSubpartA();          TransactionSubpartB();     
     TransactionSubpartC();          // EvenMoreCode;
}

class JuniorAccount : public Account {
     public:          void virtual TransactionSubpartA(); }

class SavingsAccount : public Account {
     public:          void virtual TransactionSubpartC(); }

Account*  customer;
customer = createNewAccount();
customer->Transaction(amount);

Doc 15, Functors, Command, Template Mehod Slide # 13
Polymorphism
The Good



Making modifications to program require:

Adding new subclasses

Changing code that creates objects


Account*  customer;
customer = createNewAccount();
customer->Transaction(amount);

Doc 15, Functors, Command, Template Mehod Slide # 14
Polymorphism
The Bad




The root base class needs to "know" about operations in all subclasses


Account* customer;
customer = createNewAccount();
customer->Foo(); // compile error

----------