您的位置:首页 > 其它

设计模式笔记-Command命令模式

2016-06-03 20:15 471 查看
命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。该模式实现了
请求和实现 的解耦,实现手段就是将请求抽象为一个对象。

一般的实现基本都是上面定义的前半段,请求的排队和记录,以及撤销(undo),恢复(redo)操作都可以在ConcreteCommand里实现。这时候,可以在ConcreteCommand里保存一些状态信息!



举个遥控器-电视机的例子,这里的Receiver就相当于电视吧,因为它执行命令嘛,发送命令的Invoker就相当于遥控器!

真正执行命令的接口函数都在Receiver类里,每一个ConcreteCommand类都相当于一个具体的命令,里面都放有一个Receiver类指针,只是在各自的Execute()函数里,调用的是Receiver类里不同的执行命令的函数,所以用户在使用时,通过具体的ConcreteCommand类指针来操作就行了。这里又加了一层Invoker类,它可以进行一些命令组织的操作,呈现给用户统一的接口,如果你想用什么命令,直接ConcreteCommand*
cmd->Execute(),也行啊,但这样比较乱啊!

看代码吧:

class ReceiverTV {
public:
void actionOpen() {
cout<<"Open"<<endl;
}
void actionClose() {
cout << "Close" << endl;
}
void actionChange() {
cout << "Change" << endl;
}
};
class ICommand {
public:
virtual void execute()=0;
protected:
ReceiverTV * recvTV;
};

class OpenCommand :public ICommand {
public:
OpenCommand(ReceiverTV*);
void execute();
};

class CloseCommand :public ICommand {
public:
CloseCommand(ReceiverTV*);
void execute();
};

class ChangeCommand :public ICommand {
public:
ChangeCommand(ReceiverTV*);
void execute();
};
OpenCommand::OpenCommand(ReceiverTV* recv)
{
recvTV = recv;
}
void OpenCommand::execute()
{
recvTV->actionOpen();
}

CloseCommand::CloseCommand(ReceiverTV* recv)
{
recvTV = recv;
}
void CloseCommand::execute()
{
recvTV->actionClose();
}

ChangeCommand::ChangeCommand(ReceiverTV* recv)
{
recvTV = recv;
}
void ChangeCommand::execute()
{
recvTV->actionChange();
}
class Invoker {
public:
enum CMD { OPEN, CLOSE, CHANGE };
public:
void addCommand(CMD e, ICommand *cmd) {
mapCommand[e] = cmd;
}
void runCommand(CMD e) {
mapCommand[e]->execute();
}
private:
map<CMD, ICommand*> mapCommand;
};

int main()
{
ReceiverTV* recv = new ReceiverTV();
ICommand * open = new OpenCommand(recv);
ICommand * close = new CloseCommand(recv);
ICommand * change = new ChangeCommand(recv);
Invoker *invoker = new Invoker();
invoker->addCommand(Invoker::OPEN, open);
invoker->addCommand(Invoker::CLOSE, close);
invoker->addCommand(Invoker::CHANGE, change);

invoker->runCommand(Invoker::OPEN);
invoker->runCommand(Invoker::CLOSE);
invoker->runCommand(Invoker::CHANGE);
return 0;
}
认真看一下很容易看懂,但在我心里不服务的地方就是这个Invoker类,它的实现也决定了用户(main函数)怎么用。我这里是用一个map把遥控器所有的3个命令都保存起来了,以后用户用的时候直接通过枚举参数调用runCommand函数就行了。想法是参照了这一篇,但也有别的各种实现,比如:不用map,而用vector或list等,不加区分地把命令指针保存起来,这样,命令要执行的话会全部执行,这就是Command+Composite模式;还有,也可以在Invoker里只保存一个ICommand*变量,传递进来哪个命令我就执行哪个,这样用户代码任务就增加了。各有各的使用场景,大家根据自己的需求选择。我这种实现我觉得对该例子来说合理一些,不过看着也是别扭!
贴一个Command+Composite的UML图,代码区别不大,略!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: