概念
命令模式(Command Pattern)是将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
Command模式也叫命令模式 ,是行为设计模式的一种。Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。
在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建目标对象实例;设置调用参数;调用目标对象的方法。
但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。
整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。-
调用前后需要对调用参数进行某些处理。调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。
角色和职责
Command:Command命令的抽象类。
ConcreteCommand:Command的具体实现类。
Receiver:需要被调用的目标对象。
Invorker(请求者):通过Invorker执行Command对象。
角色:
抽象命令类(Command):声明需要执行的命令,一般要对外公布一个方法来执行命令
命令类:对抽象命令类中的方法进行实现
调用者(Invoker):负责调用命令
接收者(Receiver):负责接收并执行命令
客户端(Client):最终调用类
优点
良好的封闭性(每个命令封装在一个命令类中)、扩展性
降低对象之间的耦合度
新的命令可以很容易地加入到系统中
可以比较容易地设计一个组合命令
调用同一方法实现不同的功能
缺点
针对每一个命令都需要设计一个具体命令类,因此可能会导致系统存在大量的命令类
命令过于简单时,本来几行代码可以搞定,这里就需要封装一个命令类
适用场景
适用于大多数请求-响应模式的功能
系统需要将请求调用者和请求接收者解耦时,可用命令模式使调用者和接收者不直接交互
适用于:
- 适用于大多数请求-响应模式的功能
- 系统需要将请求调用者和请求接收者解耦时,可用命令模式使调用者和接收者不直接交互
是将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
简单案例:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <queue>
#include <Windows.h>
using namespace std;
/*命令接口*/
//处理客户端请求
class HandleClientCommand{
public:
//为玩家增加金币
void addMoney(){
cout << "给玩家增加金币...." << endl;
}
//为玩家添加装备
void addEquipment(){
cout << "给玩家添加装备...." << endl;
}
//为玩家升级
void addLevel(){
cout << "给玩家升级...." << endl;
}
};
//抽象命令接口
class AbstractCommand{
public:
virtual void handle() = 0;
};
//处理增加金币需求
class AddMoneyCommand :public AbstractCommand{
public:
AddMoneyCommand(HandleClientCommand *protocol){
this->pProtocol = protocol;
}
virtual void handle(){
pProtocol->addMoney();
}
private:
HandleClientCommand* pProtocol;
};
//处理添加装备需求
class AddEquipmentCommand :public AbstractCommand{
public:
AddEquipmentCommand(HandleClientCommand *protocol){
this->pProtocol = protocol;
}
virtual void handle(){
pProtocol->addEquipment();
}
private:
HandleClientCommand* pProtocol;
};
//处理玩家升级需求
class AddLevelCommand :public AbstractCommand{
public:
AddLevelCommand(HandleClientCommand *protocol){
this->pProtocol = protocol;
}
virtual void handle(){
pProtocol->addLevel();
}
private:
HandleClientCommand* pProtocol;
};
//服务器
class Server{
public:
void addRequest(AbstractCommand* command){
mCommands.push(command);
}
void startHandle(){
while (!mCommands.empty()){
Sleep(2000);
AbstractCommand* command = mCommands.front();
command->handle();
mCommands.pop();
}
}
private:
queue<AbstractCommand* > mCommands;
};
void test(){
//协议处理类
HandleClientCommand* protocol = new HandleClientCommand;
//为玩家添加金币
AbstractCommand* addmoney = new AddMoneyCommand(protocol);
//为玩家添加装备
AbstractCommand* addequipment = new AddLevelCommand(protocol);
//为玩家升级、
AbstractCommand* addlevel = new AddLevelCommand(protocol);
//服务器类
Server* server = new Server;
//增加需求
server->addRequest(addmoney);
server->addRequest(addequipment);
server->addRequest(addlevel);
server->startHandle();
}
int main(void){
test();
return 0;
}