命令模式

设计理念

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值