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 保存的环境越多,其独立性越强。