CS 696: Advanced OO
| Functor | slide # 1 |
| Command | slide # 6 |
| Template Method | slide # 10 |
Advanced C++: Programing Styles and Idioms, James Coplien, Addison Wesley, 1992
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
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
}
}
}
We may wish to sort the same objects in different ways
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;
}
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 }
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
}
}
}
Same run-time flexibility as function pointer
Lends it self to poor abstractions
Other?
Give much more power than functor
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();
}
}
}
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
}
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();
}
}
}
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
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);
class Account {
public:
void virtual Transaction() = 0;
}
class JuniorAccount : public Account {
public
void Transaction() { put code here}
}

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);
Account* customer; customer = createNewAccount(); customer->Transaction(amount);

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