//
Purpose. Command class Deadbeat {
//
public:
// Discussion. On
the left, an IOU Deadbeat( int v
) { cash_ = v; }
// has been encapsulated as a struct, int payUp( int v ) {
// and TheBoss
class is tightly coup- cash_ -=
v; return v; }
// led to that
struct. On the right, int rptCash() { return cash_; }
//
TheBoss is only coupled to the ab-
private:
// stract class Command.
Lots of pos- int cash_;
//
sible derived classes could be sub-
};
// stituted: IOUs that call payUp() on
// Deadbeats, Checks
that call cash() class Command {
public:
// on Banks, Stocks that call redeem() virtual int execute() = 0;
// on Companies. Each "command" is a };
// "token" that gets
transfered from
// one holder to another, until some- class IOU : public Command {
// one
chooses to "execute" it.
public:
typedef int
(Deadbeat::*Meth)(int);
class Deadbeat { public: IOU(
Deadbeat* r, Meth a, int m ) {
Deadbeat( int v ) { cash_ = v; } obj_ = r;
int payUp( int v ) { mth_ = a;
cash_ -= v; return v;
} amt_ = m; }
int rptCash() { return cash_; } int execute() {
private: return
(obj_->*mth_)( amt_ ); }
int
cash_;
private:
}; Deadbeat* obj_;
Meth mth_;
struct IOU { int amt_;
Deadbeat* objPtr; };
int (Deadbeat::*funPtr)( int );
int
amt; class
Enforcer {
}; public:
Enforcer( Command& c ) : cmd_(c) {}
class Enforcer {
public: Command&
collect() { return cmd_; }
Enforcer( IOU& m ) : mkr_(m) { }
private:
IOU&
collect() { return mkr_; }
Command& cmd_;
private: };
IOU& mkr_;
}; class TheBoss {
public:
class TheBoss { TheBoss() { cash_ = 1000; }
public: collect(
Command& cmd ) {
TheBoss() {
cash_ = 1000; } cash_ +=
cmd.execute(); }
collect(
IOU& i ) { int
rptCash() { return cash_; }
cash_ +=
private:
((i.objPtr)->*i.funPtr)(i.amt) int cash_;
} };
int rptCash() { return cash_; }
private: void main(
void )
int cash_; {
};
Deadbeat joe(90), tom(90);
IOU one(&joe,
&Deadbeat::payUp, 60);
void main( void ) IOU two(&tom, &Deadbeat::payUp,
70);
{ Enforcer quido(one), lucca(two);
Deadbeat joe(90), tom(90); TheBoss don;
IOU one ={&joe, &Deadbeat::payUp,60}
IOU two ={&tom,
&Deadbeat::payUp,70} don.collect(
quido.collect() );
Enforcer
quido(one), lucca(two);
don.collect( lucca.collect() );
TheBoss don; cout <<
"joe has $" << joe.rptCash()
cout << "tom
has $" << tom.rptCash()
don.collect( quido.collect() );
cout << "don has $" << don.rptCash()
don.collect( lucca.collect() ); }
cout << "joe has $" << joe.rptCash()
cout << "tom has $"
<< tom.rptCash() // joe has $30
cout << "don has $" << don.rptCash() // tom has
$20
} // don has $1130
//
Purpose. Command design pattern
//
1. Create a class that encapsulates some number of the following:
// a "receiver" object
// the method to invoke
// the arguments to pass
// 2.
Instantiate an object for each "callback"
// 3. Pass each object
to its future "sender"
// 4. When the sender is ready to
callback to the receiver, it calls execute()
#include
<iostream> #include
<string> using namespace
std;
class Person;
class Command { // 1. Create a class that encapsulates an
object
Person* object; // and a
member function
void
(Person::*method)(); // a pointer to a
member function (the attri-
public: //
bute's name is "method")
Command( Person* obj = 0, void (Person::*meth)() = 0 ) {
object = obj; // the argument's name is "meth"
method = meth;
}
void execute() {
(object->*method)(); //
invoke the method on the object
}
};
class Person {
string name;
Command
cmd; // cmd is a
"black box", it is a method invoca-
public: // tion promoted to "full object
status"
Person( string n,
Command c ) : cmd( c ) {
name
= n;
}
void talk() { // "this" is the sender, cmd has the
receiver
cout << name
<< " is talking" << endl;
cmd.execute();
// ask the "black box" to callback the receiver
}
void passOn() {
cout
<< name << " is passing on" << endl;
cmd.execute(); // 4. When the sender is ready to callback to
} //
the receiver, it calls execute()
void gossip() {
cout
<< name << " is gossiping" << endl;
cmd.execute();
}
void listen() {
cout
<< name << " is listening" << endl;
} };
void main( void ) {
// Fred will "execute" Barney
which will result in a call to passOn()
// Barney will "execute" Betty which will result in a call to
gossip()
// Betty will
"execute" Wilma which will result in a call to listen()
Person wilma( "Wilma",
Command() );
// 2.
Instantiate an object for each "callback"
// 3. Pass each object to its future
"sender"
Person
betty( "Betty", Command( &wilma, &Person::listen ) );
Person barney( "Barney", Command(
&betty, &Person::gossip ) );
Person fred( "Fred",
Command( &barney, &Person::passOn ) );
fred.talk();
}
// Fred is
talking
// Barney is passing on
// Betty is gossiping
// Wilma
is listening
// Purpose. Simple and "macro" commands
//
//
Discussion. Encapsulate a request as an
object. SimpleCommand
// maintains
a binding between a receiver object and an action stored as a
// pointer
to a member function. MacroCommand
maintains a sequence of
// Commands.
No explicit receiver is required because the subcommands
// already
define their receiver. MacroCommand may
contain MacroCommands.
#include <iostream>
#include
<vector>
using namespace std;
class Number {
public:
void dubble( int&
value ) { value *= 2; }
};
class Command { public: virtual void
execute( int& ) = 0; };
class SimpleCommand : public Command
{
typedef void (Number::*
Action)(int&);
Number*
receiver;
Action action;
public:
SimpleCommand( Number* rec, Action act )
{
receiver = rec;
action = act;
}
/*virtual*/ void execute( int& num ) { (receiver->*action)( num
); }
};
class MacroCommand : public Command {
vector<Command*> list;
public:
void add( Command* cmd ) { list.push_back(
cmd ); }
/*virtual*/ void
execute( int& num ) {
for (int i=0; i < list.size(); i++)
list[i]->execute( num );
} };
void main( void ) {
Number object;
Command* commands[3];
commands[0] = &SimpleCommand(
&object, &Number::dubble );
MacroCommand two;
two.add( commands[0] );
two.add( commands[0] );
commands[1] = &two;
MacroCommand four;
four.add( &two ); four.add(
&two );
commands[2] =
&four;
int num,
index;
while (true) {
cout
<< "Enter number selection (0=2x 1=4x 2=16x): ";
cin >> num >> index;
commands[index]->execute( num
);
cout << " " << num << '\n';
} }
// Enter number selection (0=2x
1=4x 2=16x): 3 0
// 6
//
Enter number selection (0=2x 1=4x 2=16x): 3 1
// 12
// Enter number selection (0=2x 1=4x 2=16x): 3 2
// 48
// Enter number selection (0=2x
1=4x 2=16x): 4 0
// 8
//
Enter number selection (0=2x 1=4x 2=16x): 4 1
// 16
// Enter number selection (0=2x 1=4x 2=16x): 4 2
// 64
//
Purpose. Command design pattern and
inheritance
//
// Discussion.
The Command pattern promotes a deferred method invocation to
//
full object status. Each Command object
is a "black box" - it is opaque to
// its holder/user. Here, a portfolio's heterogeneous collection
of financial
// instruments is being treated homogeneously, because, they
all inherit from
// a common base class, and, they all have a
"convert to currency" method with
// a common signature.
#include
<iostream>
using namespace std;
class Instrument {
public: virtual ~Instrument() { } };
class IOU : public Instrument
{
int amount;
public:
IOU( int in ) { amount = in; }
int payUp() { return amount; }
};
class
Check : public Instrument {
int
amount;
public:
Check( int
in ) { amount = in; }
int cash()
{ return amount; }
};
class Stock : public Instrument {
int amount;
public:
Stock( int in ) { amount = in; }
int redeem() { return amount; }
};
class
Command {
public:
typedef
int (Instrument::*Action)();
Command( Instrument* o, Action m ) {
object = o;
method = m;
}
int execute() { return
(object->*method)(); }
private:
Instrument* object;
Action method;
};
void
main( void ) {
Command*
portfolio[] = { // old C cast, or new
RTTI is required
&Command( &IOU(100),
(int(Instrument::*)())&IOU::payUp ),
&Command( &Check(200),
static_cast<int(Instrument::*)()>(&Check::cash) ),
&Command( &Stock(300),
static_cast<int(Instrument::*)()>(&Stock::redeem) ) };
for (int netWorth=0, i=0; i < 3;
i++)
netWorth +=
portfolio[i]->execute();
cout
<< "net worth is now " << netWorth << '\n';
}
//
net worth is now 600
// Purpose. Command design pattern and class
template
#include <iostream>
#include
<string>
using namespace std;
class A {
int divisor;
public:
A( int div ) { divisor = div; }
int divide( int in ) { return in / divisor;
}
int modulus( int in ) { return
in % divisor; }
};
class B {
string str;
public:
B( string s ) { str = s; }
string prepend( string in ) {
return in + str; }
string
postpend( string in ) { return str + in; }
};
template
<typename CLS, typename ARG>
class Command {
public:
typedef ARG (CLS::*Action)( ARG );
Command( CLS* o, Action m, ARG a ) {
object = o;
method = m;
argument = a;
}
ARG execute() { return (object->*method)( argument ); }
private:
CLS*
object;
Action
method;
ARG argument;
};
void main(
void ) {
Command<A,int>*
list1[4] = {
&Command<A,int>( &A(3), &A::divide, 16 ),
&Command<A,int>( &A(3), &A::modulus, 16
),
&Command<A,int>(
&A(4), &A::divide, 16 ),
&Command<A,int>( &A(4),
&A::modulus, 16 ) };
for
(int i=0; i < 4; i++)
cout
<< "numbers are " << list1[i]->execute() <<
'\n';
B
obj("abc");
Command<B,string>* list2[4] = {
new Command<B,string>( &obj, &B::prepend, "123" ),
new Command<B,string>( &obj,
&B::prepend, "xyz"
),
new
Command<B,string>( &obj, &B::postpend, "123" ),
new Command<B,string>( &obj,
&B::postpend, "xyz" ) };
for (i=0; i < 4; i++)
cout << "strings are " << list2[i]->execute()
<< '\n';
}
// numbers are 5
// numbers are 1
//
numbers are 4
// numbers are 0
// strings are 123abc
// strings
are xyzabc
// strings are abc123
// strings are abcxyz
//
Purpose. Command/Adapter design pattern
(External Polymorphism demo)
// 1. Specify the new desired
interface
// 2. Design a "wrapper" class that can
"impedance match" the old to the new
// 3. The client uses (is
coupled to) the new interface
// 4. The wrapper/adapter "maps"
to the legacy implementation
#include <iostream.h>
class
ExecuteInterface { public:
// 1. Specify the new i/f
virtual ~ExecuteInterface() { }
virtual void execute() = 0;
};
template <class
TYPE> //
2. Design a "wrapper" or
class ExecuteAdapter : public ExecuteInterface
{ //
"adapter" class
public:
ExecuteAdapter( TYPE* o, void (TYPE::*m)() ) { object = o; method =m; }
~ExecuteAdapter() { delete object; }
// 4. The adapter/wrapper "maps"
the new to the legacy implementation
void execute() /* the
new */ { (object->*method)();
}
private:
TYPE* object; //
ptr-to-object attribute
void
(TYPE::*method)(); /* the old */ // ptr-to-member-function
};
// attribute
// The
old: three totally incompatible classes
// no common base class,
class Fea { public: // no hope of
polymorphism
~Fea() { cout << "Fea::dtor"
<< endl; }
void doThis() {
cout << "Fea::doThis()" << endl; }
};
class
Feye { public:
~Feye() { cout << "Feye::dtor"
<< endl; }
void doThat() {
cout << "Feye::doThat()" << endl; }
};
class
Pheau { public:
~Pheau() { cout << "Pheau::dtor" << endl; }
void doTheOther() { cout <<
"Pheau::doTheOther()" << endl; }
};
/* the new
is returned */ ExecuteInterface** initialize() {
ExecuteInterface** array = new
ExecuteInterface*[3]; /* the old is below */
array[0] = new ExecuteAdapter<Fea>( new Fea(), &Fea::doThis
);
array[1] = new
ExecuteAdapter<Feye>( new
Feye(), &Feye::doThat );
array[2] = new ExecuteAdapter<Pheau>( new Pheau(), &Pheau::doTheOther );
return array;
}
void main(
void ) {
ExecuteInterface**
objects = initialize();
for (int i=0; i < 3; i++) objects[i]->execute(); // 3. Client uses the new
// (polymporphism)
for (i=0; i < 3; i++) delete
objects[i];
delete
objects;
}
// Fea::doThis()
// Feye::doThat()
//
Pheau::doTheOther()
// Fea::dtor
// Feye::dtor
//
Pheau::dtor
// Purpose. Command design pattern demo
//
// Discussion. Encapsulate a request as an object. SimpleCommand
// maintains a binding between
a receiver object and an action stored as a
// pointer to a member
function. MacroCommand maintains a
sequence of
// Commands. No
explicit receiver is required because the subcommands
// already define
their receiver. MacroCommand may
contain MacroCommands.
#include <iostream.h>
class
Number {
public:
Number(
int value ) { _value = _copy = value; }
int getValue() { return _value; }
void
increment() { _copy = _value++;
}
void decrement() { _copy = _value--; }
void restore() { _value = _copy; }
void
dubble() { _copy = _value; _value = 2 * _value; }
void half() { _copy = _value;
_value = _value / 2; }
void
square() { _copy = _value; _value = _value * _value; }
private:
int _value;
int _copy;
};
class Command {
public:
virtual void execute() = 0;
virtual void add( Command* ) { }
protected:
Command() { }
};
class
SimpleCommand : public Command {
public:
typedef void (Number::* Action)();
SimpleCommand( Number* receiver, Action action ) {
_receiver = receiver;
_action = action; }
virtual void execute() {
(_receiver->*_action)(); }
protected:
Number* _receiver;
Action _action;
};
class
MacroCommand : public Command {
public:
MacroCommand() { _numCommands = 0; }
void add( Command* cmd ) {
_list[_numCommands++] = cmd; }
virtual
void execute();
private:
Command*
_list[10];
int _numCommands;
};
void
MacroCommand::execute() {
for
(int i=0; i < _numCommands; i++)
_list[i]->execute();
}
void
main() {
int i;
cout << "Integer: ";
cin >> i;
Number*
object = new Number(i);
Command* commands[9];
commands[1] = new SimpleCommand( object, &Number::increment
);
commands[2] = new
SimpleCommand( object, &Number::decrement );
commands[3] = new SimpleCommand( object, &Number::dubble
);
commands[4] = new
SimpleCommand( object, &Number::half );
commands[5] = new SimpleCommand( object, &Number::square
);
commands[6] = new
SimpleCommand( object, &Number::restore );
commands[7] = new MacroCommand;
commands[7]->add( commands[1] );
commands[7]->add( commands[3] );
commands[7]->add( commands[5] );
commands[8] = new MacroCommand;
commands[8]->add( commands[7] );
commands[8]->add( commands[7] );
cout << "Exit[0], ++[1], --[2],
x2[3], Half[4], Square[5], "
<<
"Undo[6], do3[7] do6[8]: ";
cin
>> i;
while
(i)
{
commands[i]->execute();
cout << " " << object->getValue()
<< endl;
cout
<< "Exit[0], ++[1], --[2], x2[3], Half[4], Square[5], "
<< "Undo[6], do3[7]
do6[8]: ";
cin
>> i;
}
}
//
Integer: 4
// Exit[0], ++[1], --[2], x2[3], Half[4], Square[5], Undo[6],
do3[7] do6[8]: 1
// 5
//
Exit[0], ++[1], --[2], x2[3], Half[4], Square[5], Undo[6], do3[7] do6[8]:
3
// 10
// Exit[0], ++[1],
--[2], x2[3], Half[4], Square[5], Undo[6], do3[7] do6[8]: 2
// 9
// Exit[0], ++[1], --[2], x2[3],
Half[4], Square[5], Undo[6], do3[7] do6[8]: 4
// 4
// Exit[0], ++[1], --[2], x2[3], Half[4], Square[5],
Undo[6], do3[7] do6[8]: 5
//
16
// Exit[0], ++[1], --[2], x2[3], Half[4], Square[5], Undo[6],
do3[7] do6[8]: 6
// 4
//
Exit[0], ++[1], --[2], x2[3], Half[4], Square[5], Undo[6], do3[7] do6[8]:
6
// 4
// Exit[0], ++[1],
--[2], x2[3], Half[4], Square[5], Undo[6], do3[7] do6[8]: 7
// 100
// Exit[0], ++[1], --[2], x2[3],
Half[4], Square[5], Undo[6], do3[7] do6[8]: 6
// 10
// Exit[0], ++[1], --[2], x2[3], Half[4], Square[5],
Undo[6], do3[7] do6[8]: 8
//
940900