Command对象是一个“和其实际执行着分开存储”的组件。其重要目的是降低系统中两个部分(请求者 invoker 和接收者 receiver )之间的依存性。
典型的行为次序:
1 客户端产生一个 ConcreteCommand 对象,并传给它足够信息以备执行某项任务。
2 客户端将 ConcreteCommand 对象中的 Command 接口传给 invoker(请求者),由它保存这个接口。
3 此后,一旦调用者认为执行时机已到,便启动 Command 的 Execute() 虚函数。虚拟调用机制会将这个调用动作发给 ConcreteCommand 对象,由后者处理细节。第一种情况是找到 Receiver 对象(任务执行者),并通过该对象实际进行处理,称此类命令为转发式命令。另一种情况是有 ConcreateCommand 对象全权处理,此时 receiver 不复存在,此类命令称为主动式命令。
class ICommand { public: virtual void Excute() = 0; virtual ~ICommand() {} }; class Receiver { public: void Action() { cout << "Command is executing" << endl; } }; class ConcreateCommand : public ICommand { typedef void(Receiver::*PCmdFunc)(/*argments list*/); public: ConcreateCommand(Receiver *pReceiver, PCmdFunc pCmd/*, argments list*/) : pReceiver_(NULL) , pCmdFunc_(NULL) { pReceiver_ = pReceiver; pCmdFunc_ = pCmd; } public: void Excute() { (pReceiver_->*pCmdFunc_)(); } private: PCmdFunc pCmdFunc_; Receiver *pReceiver_; }; class ActionCommand : public ICommand { public: void Excute() { // 包含由 Receiver 对象中 Action 函数中的所有行为 // ... cout << "Command is excuting" << endl; } }; class Invoker { public: Invoker(ICommand *pCommand) : pCommand_(NULL) { pCommand_ = pCommand; } public: void invoke() { if (pCommand_ != NULL) pCommand_->Excute(); } private: ICommand *pCommand_; }; int main() { // 第一种情况:Receiver 对象为任务执行者,实际进行处理 Receiver receiver; ConcreateCommand cmd(&receiver, &Receiver::Action); // 第二种情况:由 ConcreteCommand 对象全权处理 ActionCommand actionCmd; // 各种 ConcreteCommand 对象注册到 Invoker 对象中 Invoker invoker(&cmd); Invoker invoker2(&actionCmd); // 在需要的时刻启用 Command invoker.invoke(); invoker2.invoke(); return 0; }
这些反映了 Command 模式的两个特点:
*接口分离。invoker 和 receiver 分离。
*时间分离。 Command 保存了一个整装待发的处理请求,供将来调用。
环境概念也很重要。某执行点的“环境”指的是该执行点可见的一组实体(变量和函数)。当处理动作真正开始进行时,必要的环境必须准备就绪,否则处理动作无法执行开来。ConcreteCommand 对象将必要环境的一部分当做自身转改保存起来,并在执行 Execute() 期间取用其中部分消息。ConcreateCommand 保存的环境越多,其独立性越强。