//
Purpose. Command design pattern lab
//
// Problem. Encapsulation is an
excellent tool for mitigating complexity.
// Here, the notion of a
"command" has been designed that encapsulates a
// request to be
performed on a "second party" object. This encapsulating
// abstraction can now be handed to a
"third party" object that provides
// some interesting
"service" for the "first party" application. As far as
// the Queue object is
concerned, Command objects are opaque black boxes.
// This demo models the
"first party" as really two separate entities: the
// entity
responsible for "queueing up" Commands, and the entity
responsible
// for "dequeueing" and executing commands. The latter entity is obliged to
//
"query" the type of each Command as it comes off the queue, and then
step
// through a multiple branch conditional construct to identify the
correct
// action to take.
Optimally, none of this would be necessary if the
// Command
abstraction were appropriately "objectified".
//
//
Assignment.
// o Convert Command from a struct to a class
// o Remove
the "type" field from the Command class
// o Add the following
"pointer to member function" declaration to Command
// "typedef void (File::* Action
)();"
// o Add an "Action" private data member to
Command
// o Replace the "unarchive", "transfer", and
"compress" initialization
//
arguments with arguments of the form
"&File::unarchive"
// o Add an execute() method to Command
that simply calls action_ on receiver_
// ( "(receiver_->*action_)()" )
// o Remove the
"type query" expressions from main()
// o Replace the multiple
branch conditional construct with a single call to
// execute()
#include
<iostream.h>
#include <string.h>
struct
Command;
class Queue {
public:
Queue() {
add_
= remove_ = 0; }
void enque(
Command* c ) {
array_[add_] =
c;
add_ = (add_ + 1) % SIZE;
}
Command* deque() {
int temp = remove_;
remove_ = (remove_ + 1) % SIZE;
return array_[temp]; }
private:
enum { SIZE = 10 };
Command*
array_[SIZE];
int add_;
int remove_;
};
class
File {
public:
File( char*
n ) { strcpy( name_, n ); }
void
unarchive() { cout << "unarchive " << name_ <<
endl; }
void compress() { cout << "compress " << name_ << endl; }
void transfer() { cout << "transfer " << name_ << endl; }
private:
char
name_[30];
};
enum Action { unarchive, transfer, compress };
struct Command
{
Command( File* f, Action a ) {
receiver = f; action = a; }
File* receiver;
Action
action;
};
Command* input[8] = {
new Command( new
File("irImage.dat"),
unarchive ),
new Command(
new File("screenDump.jpg"), transfer ),
new Command( new
File("paper.ps"),
unarchive ),
new Command(
new File("widget.tar"),
compress ),
new Command(
new File("esmSignal.dat"),
unarchive ),
new Command(
new File("msword.exe"),
transfer ),
new Command(
new File("ecmSignal.dat"),
compress ),
new Command(
new File("image.gif"),
transfer )
};
void main( void )
{
Queue
que;
Command*
cmd;
int i;
for (i=0; i < 8; i++)
que.enque( input[i] );
for (i=0; i < 8; i++)
{
cmd = que.deque();
if (cmd->action == unarchive)
cmd->receiver->unarchive();
else if (cmd->action ==
transfer)
cmd->receiver->transfer();
else if (cmd->action == compress)
cmd->receiver->compress();
}
}
// unarchive irImage.dat
// transfer
screenDump.jpg
// unarchive paper.ps
// compress widget.tar
//
unarchive esmSignal.dat
// transfer msword.exe
// compress
ecmSignal.dat
// transfer image.gif