命令模式

来源:互联网 发布:明解c语言pdf 编辑:程序博客网 时间:2024/06/05 20:48

设计理念

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化; 对请求排队或记录请求日志,以及支持可撤销的操作。

命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。

考虑现实我们在开发的过程中经常会遇到这样的场景吧:我们需要执行一个时间特别长的任务,如果我们将这个长任务与其他的任务一起采用同步执行的方式,就会阻塞其他任务的运转,这个时候,我们可能通过异步命令的方式来操作,就能大大提升CPU的使用率。

在游戏编程中,命令模式也是常客。如果将按键与对应的执行命令硬编码,虽然可以正常的工作但也存在很大的局限,如若使用命令模式将请求者和接受者解耦,通过在命令和角色间增加了一层重定向, 我们获得了一个灵巧的功能:我们可以让玩家控制游戏中的任何角色,只需向命令传入不同的角色。

UML框图

命令模式

  • Command: 抽象命令类,定义命令的接口,申明执行的方法;
  • ConcreteCommand:具体命令类,实现要执行的方法,它通常是“虚”的表现;通常会有接受者,并调用接受者的功能来完成命令要执行的操作;
  • Invoker: 调用者,要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象;
  • Receiver: 接收者,真正执行命令的对象;
  • Client:客户类,最终的客户端调用类。

实现代码

//main.cpp#include <iostream>#include "ConcreteCommand.h"#include "Invoker.h"#include "Receiver.h"using namespace std;int main(int argc, char *argv[]){    Receiver * pReceiver = new Receiver();    ConcreteCommand * pCommand = new ConcreteCommand(pReceiver);    Invoker * pInvoker = new Invoker(pCommand);    pInvoker->call();    delete pReceiver;    delete pCommand;    delete pInvoker;    return 0;}
/////////////////////////////////////////////////////////////  Receiver.h//  Implementation of the Class Receiver///////////////////////////////////////////////////////////class Receiver{public:    Receiver();    virtual ~Receiver();    void action();};
/////////////////////////////////////////////////////////////  Receiver.cpp//  Implementation of the Class Receiver///////////////////////////////////////////////////////////#include "Receiver.h"#include <iostream>using namespace std;Receiver::Receiver(){}Receiver::~Receiver(){}void Receiver::action(){    cout << "receiver action." << endl;}
/////////////////////////////////////////////////////////////  ConcreteCommand.h//  Implementation of the Class ConcreteCommand///////////////////////////////////////////////////////////#include "Command.h"#include "Receiver.h"class ConcreteCommand : public Command{public:    ConcreteCommand(Receiver * pReceiver);    virtual ~ConcreteCommand();    virtual void execute();private:    Receiver *m_pReceiver;};
/////////////////////////////////////////////////////////////  ConcreteCommand.cpp//  Implementation of the Class ConcreteCommand///////////////////////////////////////////////////////////#include "ConcreteCommand.h"#include <iostream>using namespace std;ConcreteCommand::ConcreteCommand(Receiver *pReceiver){    m_pReceiver = pReceiver;}ConcreteCommand::~ConcreteCommand(){}void ConcreteCommand::execute(){    cout << "ConcreteCommand::execute"  << endl;    m_pReceiver->action();}
/////////////////////////////////////////////////////////////  Invoker.h//  Implementation of the Class Invoker///////////////////////////////////////////////////////////#include "Command.h"class Invoker{public:    Invoker(Command * pCommand);    virtual ~Invoker();    void call();private:    Command *m_pCommand;};
/////////////////////////////////////////////////////////////  Invoker.cpp//  Implementation of the Class Invoker///////////////////////////////////////////////////////////#include "Invoker.h"#include <iostream>using namespace std;Invoker::Invoker(Command * pCommand){    m_pCommand = pCommand;}Invoker::~Invoker(){}void Invoker::call(){    cout << "invoker calling" << endl;    m_pCommand->execute();}

总结

命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
命令模式的主要优点在于降低系统的耦合度,增加新的命令很方便,而且可以比较容易地设计一个命令队列和宏命令,并方便地实现对请求的撤销和恢复;其主要缺点在于可能会导致某些系统有过多的具体命令类。

参考链接

http://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/command.html
http://gpp.tkchu.me/command.html