Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
The Command pattern is structurally very simple, but can
have an important impact on decoupling and thus cleaning up your code.
In Advanced C++: Programming Styles And Idioms (Addison Wesley,
1992), Jim Coplien coins the term functor which is an object whose
sole purpose is to encapsulate a function (since functor has a meaning in
mathematics, we shall use the more explicit term function object). The point is to decouple the choice of function to be called from the site
where that function is called.
This term is mentioned but not used in GoF. However, the
theme of the function object is repeated in a number of patterns in that book.
A Command is a function object in its purest sense: a
function that s an object. By wrapping a function in an object, you can pass it
to other functions or objects as a parameter, to tell them to perform this
particular operation in the process of fulfilling your request. You could say
that a Command is a Messenger that carries behavior.
//: C10:CommandPattern.cpp
#include <iostream>
#include <vector>
using namespace std;
class Command {
public:
virtual void execute() = 0;
};
class Hello : public Command {
public:
void execute() { cout << "Hello "; }
};
class World : public Command {
public:
void execute() { cout << "World! "; }
};
class IAm : public Command {
public:
void execute() { cout << "I'm the command
pattern!"; }
};
// An object that holds commands:
class Macro {
vector<Command*> commands;
public:
void add(Command* c) { commands.push_back(c); }
void run() {
vector<Command*>::iterator it =
commands.begin();
while(it != commands.end())
(*it++)->execute();
}
};
int main() {
Macro macro;
macro.add(new Hello);
macro.add(new World);
macro.add(new IAm);
macro.run();
} ///:~
The primary point of Command is to allow you to hand a
desired action to a function or object. In the above example, this provides a
way to queue a set of actions to be performed collectively. Here, you can dynamically
create new behavior, something you can normally only do by writing new code but
in the above example could be done by interpreting a script (see the Interpreter
pattern if what you need to do gets very complex).
GoF says that Commands are an object-oriented replacement
for callbacks. However,
we think that the word back is an essential part of the concept of
callbacks a callback reaches back to the creator of the callback. On the other
hand, with a Command object you typically just create it and hand it to some function
or object, and you are not otherwise connected over time to the Command object.
A common example of Command is the implementation of undo
functionality in an application. Each time the user performs an operation, the
corresponding undo Command object is placed into a queue. Each Command object
that is executed backs up the state of the program by one step.
Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |