Design Patterns
Command
Design Pattern Type: Behavioral
GoF Statement of Intent:

|
Encapsulate a request as an object, thereby letting you parameterize other
objects with different requests, queue or log requests, and support undoable
operations.
|
Brief Overview:

|
An object is used to represent and encapsulate all the information needed to
call a method on an object at a later time. This may include the method name,
the object that contains the method and the arguments to be passed to the method.
The Client instantiates the command object and provides all the information
required to make the call at a later time. The Invoker decides when the
method should be called. The Receiver is an instance of the class that
contains the code for the method being called. This allows the creation of objects
(the invokers) which can execute methods at the time of their choosing without
needing to know the owner of the method or the parameters.
|
UML Diagram:
|
|
Discussion and In-class Example:
In the Command Design Pattern we used two examples. In the first we illustrated the basic
idea of the Command where a customer (Client) enters the Objectville Diner and places
an order (Command) with Flo,s the waitress (Invoker). Flo doesn't know anything
about how to prepare the customer's order. All she does is give the order (calls
command.execute()) to Earl, the short-order cook (Receiver). Earl is the one
who knows how to prepare the customer's meal (perform the require action). We say
that the Invoker is decoupled from the Command, i.e. Flo doesn't need to know anything
about preparing food. She is just the "messanger".
We also looked at the example of the home remote control and saw how to decouple the
button pressing (Invoker) from the command (Receiver) objects. We
also saw how simple it was to add the undo action by adding an undo() function to
each Command object.
Header Defining a RemoteControl class
class RemoteControl
{
private:
Command *onCommands[7];
Command *offCommands[7];
Command *undoCommand;
public:
RemoteControl();
void setCommand(int slot,
Command *onCommand,
Command *offCommand);
void onButtonPushed(int slot);
void offButtonPushed(int slot);
}
Implementation of the RemoteControl class
//--------------------------------
// Constructor - initializes all
// commands to NoCommand
//--------------------------------
RemoteControl::RemoteControl()
{
for(int i=0; i<7; i++)
{
onCommands[i] = new NoCommand();
offCommands[i] = new NoCommand();
}
undoCommand = new NoCommand();
}
//--------------------------------
// Set an on and off command for
// a particular slot.
//--------------------------------
void RemoteControl::setCommand(int slot,
Command onCommand,
Command offCommand)
{
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
//--------------------------------
// Execute an "ON" button pressed
// action.
//--------------------------------
void RemoteControl::onButtonPushed(int slot)
{
onCommands[slot]->execute();
undoCommand = onCommands[slot];
}
//--------------------------------
// Execute an "OFF" button pressed
// action.
//--------------------------------
void RemoteControl::offButtonPushed(int slot)
{
offCommands[slot]->execute();
undoCommand = offCommands[slot];
}
//---------------------------------
// Execute an "UNDO" button pressed
// action.
//---------------------------------
void RemoteControl::undoButtonPushed()
{
undoCommand->undo;
}
UML Class diagram of the NoCommand class
Implementation of the LightOn command class
class LightOnCommand::Command
{
private:
Light *light;
public:
LightOnCommand(Light *light)
{
this->light = light;
}
void execute()
{
light->on();
}
void undo()
{
light->off();
}
}
Implementation of the LightOFF command class
class LightOffCommand::Command
{
private:
Light *light;
public:
LightOffCommand(Light *light)
{
this->light = light;
}
void execute()
{
light->off();
}
void undo()
{
light->on();
}
}