Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 397, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

设计模式之command模型

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()放到一个多线程处理的“计时器”对象中,由此创建一个线程的方案。

posted on 2009-04-12 08:24 Benjamin 阅读(445) 评论(0)  编辑 收藏 引用 所属分类: C/C++


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理