C++设计模式11——命令(Command)模式
1. 命令(Command)模式介绍
定义:
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。
模式的结构:
- 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
- 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
类图:
2. 为了方便理解,举个例子
设计一套请求,通过命令接口给服务器发送请求,服务器处理请求
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<queue>
#include<unistd.h>
using namespace std;
//协议处理类
class HandleClientProtocol{
public:
//处理增加金币
void AddMoney(){
cout << "给玩家增加金币!" << endl;
}
//处理增加钻石
void AddDiamond(){
cout << "给玩家增加钻石!" << endl;
}
//处理玩家装备
void AddEquipment(){
cout << "给玩家穿装备!" << endl;
}
//处理玩家升级
void addLevel(){
cout << "给玩家升级!" << endl;
}
};
//命令接口
class AbstractCommand{
public:
virtual void handle() = 0; //处理客户端请求的接口
};
//处理增加金币请求
class AddMoneyCommand :public AbstractCommand{
public:
AddMoneyCommand(HandleClientProtocol* protocol){
this->pProtocol = protocol;
}
virtual void handle(){
this->pProtocol->AddMoney();
}
public:
HandleClientProtocol* pProtocol;
};
//处理增加钻石的请求
class AddDiamondCommand :public AbstractCommand{
public:
AddDiamondCommand(HandleClientProtocol* protocol){
this->pProtocol = protocol;
}
virtual void handle(){
this->pProtocol->AddDiamond();
}
public:
HandleClientProtocol* pProtocol;
};
//处理玩家穿装备的请求
class AddEquipmentCommand : public AbstractCommand{
public:
AddEquipmentCommand(HandleClientProtocol* protocol){
this->pProtocol = protocol;
}
virtual void handle(){
this->pProtocol->AddEquipment();
}
public:
HandleClientProtocol* pProtocol;
};
//处理玩家升级的请求
class AddLevelCommand : public AbstractCommand{
public:
AddLevelCommand(HandleClientProtocol* protocol){
this->pProtocol = protocol;
}
virtual void handle(){
this->pProtocol->addLevel();
}
public:
HandleClientProtocol* pProtocol;
};
//服务器程序
class Serser{
public:
void addRequest(AbstractCommand* command){
mCommands.push(command);
}
void startHandle(){
while (!mCommands.empty()){
sleep(2000);
AbstractCommand* command = mCommands.front();
command->handle();
mCommands.pop();
}
}
public:
queue<AbstractCommand*> mCommands;
};
void test(void){
HandleClientProtocol* protocol = new HandleClientProtocol;
//客户端增加金币的请求
AbstractCommand* addmoney = new AddMoneyCommand(protocol);
//客户端增加钻石的请求
AbstractCommand* adddiamond = new AddDiamondCommand(protocol);
//客户端穿装备的请求
AbstractCommand* addequpment = new AddEquipmentCommand(protocol);
//客户端升级请求
AbstractCommand* addlevel = new AddLevelCommand(protocol);
Serser* server = new Serser;
//将客户端请求加入到处理的队列中
server->addRequest(addmoney);
server->addRequest(adddiamond);
server->addRequest(addequpment);
server->addRequest(addlevel);
//服务器开始处理请求
server->startHandle();
}
int main(void){
test();
return 0;
}
3. 命令(Command)模式优缺点
命令模式的主要优点如下。
- 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
- 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
其缺点是:
- 可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。