1定义
将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求队列或者记录请求日志,可以提供命令的撤销和恢复功能
2类图
角色描述:
Receiver接受者角色,就是干活的码农,命令传递打这里就应该被执行。
Command命令角色,对命令额封装,所有命令声明在此
Invoker调用者角色,接受到命令并且执行命令
class Receiver
{
protected:
Receiver();
public:
virtual ~Receiver() = 0;
virtual void doSomething()=0;
};
class ConcreteReceiver:public Receiver
{
public:
void doSomething()
{
cout << "doSomething...."<<endl;
}
};
claas Command
{
protected:
Command();
public:
virtual ~Command() = 0;
virtual void execute() = 0;
};
class ConcreteCommand:public Command
{
public:
ConcreteCommand(Receiver* re)
:_receiver(re)
{}
~ConcreteCommand(){}
void execute()
{
_receiver.doSomething();
}
protected:
Receiver * _receiver;
};
class Invoke
{
private:
Command * _cmd;
public:
void setCommand(Command * cmd)
{
_cmd = cmd;
}
void action()
{
_cmd->execute();
}
};
4应用
① 优点
类间解耦
可扩展性
结合其他模式更加优秀:结合责任链模式实现命令族解析任务;结合模板方法,减少Command子类的膨胀
②缺点
命令越多,类约膨胀,需要慎用
③使用场景
只要认为是命令的地方。eg GUI 开发,按钮,DOS命令模拟,触发反馈机制的处理等
5扩展
①当一个命令需要多个接收者/执行者时,可以在命令内set多个接受者,完成通力合作的问题
②反悔问题,这个就设计备忘录模式了。或者通过反向链式存储机制得到前次记录,实现回滚。rollback
注:在项目中,约定的优先级最高,每个命令都是对一个或者多个接受者的封装。在项目中可以通过有意义的命名来实现Client和Receiver间的依赖描述
6提升
可以将接受者在Command中进行封装以及默认的指定。从而命令的单一职责,与接受者无关 且 高层无需了解调用时的接受者是谁
7命令模式练习
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <list>
using namespace std;
//命令的最终执行者
class Cooker
{
public:
//烤串
void makeChuaner() {
cout << "烤串师傅进行了烤串" << endl;
}
//烤鸡翅
void makeChicken() {
cout << "烤串师傅进行了烤鸡翅" << endl;
}
};
//烤串的 抽象的 菜单
class Command
{
public:
Command(Cooker *cooker)
{
this->cooker = cooker;
}
~Command() {
if (this->cooker != NULL) {
delete this->cooker;
this->cooker = NULL;
}
}
//菜单让最终的执行者干活的方法
virtual void execute() = 0;
protected:
Cooker *cooker;
};
//烤串的菜单
class CommandChuaner :public Command
{
public:
CommandChuaner(Cooker *cooker) : Command(cooker) {}
virtual void execute() {
//命令 最终让执行者干的工作。
this->cooker->makeChuaner();
}
};
//烤鸡翅的菜单
class CommandChicken :public Command
{
public:
CommandChicken(Cooker * cooker) : Command(cooker) {}
virtual void execute() {
//命令 最终让执行者干的工作。
this->cooker->makeChicken();
}
};
//管理所有命令的一个模块
//服务员MM
class Waitress
{
public:
//给服务员添加菜单的方法
void setCmd(Command *cmd)
{
this->cmd_list.push_back(cmd);
}
//让服务员mm 下单
void notify() {
list<Command *>::iterator it = cmd_list.begin();
for (; it != cmd_list.end(); it++) {
(*it)->execute(); //在此发生了多态
}
}
private:
list<Command *> cmd_list;
};
int main(void)
{
Waitress *mm = new Waitress;
Command *chuanger = new CommandChuaner(new Cooker);
Command *chicken = new CommandChicken(new Cooker);
//把订单都给服务员
mm->setCmd(chuanger);
mm->setCmd(chicken);
//让服务员下单,最终让师傅干活
mm->notify();
delete mm;
return 0;
}