Command(命令):选择操作模型,大体上我们可以理解此类设计模型是个函数对象,将函数封装为对象,以参数传递给其他对象或函数,以告诉它们在履行过程中执行特定的操作。
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();
} ///
GoF认为command是替代callback的面向对象的替代物,command常用的一个例子就是“撤销(undo)”操作;一个典型的command模式仅仅创建它并把它传递给一个函数或对象。是下面的示例代码如何消除正常操作和事件处理的decouling(耦合),在事件驱动编程中。
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
// Framework for running tasks:
class Task {
public:
virtual void operation() = 0;
};
class TaskRunner {
static vector<Task*> tasks;
TaskRunner() {} // Make it a Singleton
TaskRunner& operator=(TaskRunner&); // Disallowed
TaskRunner(const TaskRunner&); // Disallowed
static TaskRunner tr;
public:
static void add(Task& t) { tasks.push_back(&t); }
static void run() {
vector<Task*>::iterator it = tasks.begin();
while(it != tasks.end())
(*it++)->operation();
}
};
TaskRunner TaskRunner::tr;
vector<Task*> TaskRunner::tasks;
class EventSimulator {
clock_t creation;
clock_t delay;
public:
EventSimulator() : creation(clock()) {
delay = CLOCKS_PER_SEC/4 * (rand() % 20 + 1);
cout << "delay = " << delay << endl;
}
bool fired() {
return clock() > creation + delay;
}
};
// Something that can produce asynchronous events:
class Button {
bool pressed;
string id;
EventSimulator e; // For demonstration
public:
Button(string name) : pressed(false), id(name) {}
void press() { pressed = true; }
bool isPressed() {
if(e.fired()) press(); // Simulate the event
return pressed;
}
friend ostream&
operator<<(ostream& os, const Button& b) {
return os << b.id;
}
};
// The Command object
class CheckButton : public Task {
Button& button;
bool handled;
public:
CheckButton(Button & b) : button(b), handled(false) {}
void operation() {
if(button.isPressed() && !handled) {
cout << button << " pressed" << endl;
handled = true;
}
}
};
// The procedures that perform the main processing. These
// need to be occasionally "interrupted" in order to
// check the state of the buttons or other events:
void procedure1() {
// Perform procedure1 operations here.
// ...
TaskRunner::run(); // Check all events
}
void procedure2() {
// Perform procedure2 operations here.
// ...
TaskRunner::run(); // Check all events
}
void procedure3() {
// Perform procedure3 operations here.
// ...
TaskRunner::run(); // Check all events
}
int main() {
srand(time(0)); // Randomize
Button b1("Button 1"), b2("Button 2"), b3("Button 3");
CheckButton cb1(b1), cb2(b2), cb3(b3);
TaskRunner::add(cb1);
TaskRunner::add(cb2);
TaskRunner::add(cb3);
cout << "Control-C to exit" << endl;
while(true) {
procedure1();
procedure2();
procedure3();
}
}
说明:这里command对象由Task表示,EventSimoulator创建一个随机延迟事件,它的对象在Button中使用,用来模拟某个不可预知的时间段用户事件发生的动作。CheckButton是Task的实现,我们也可以把Taskrunner::run()放到一个多线程处理的“计时器”对象中,由此创建一个线程的方案。