什么是命令模式
命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
命令模式可用来消除程序中的耦合问题。每个“常规”的操作必须周期性地调用一个函数来检查事件的状态,而通过命令模式,这些“常规”操作不需要知道有关它们所检查的事件的任何信息,也就是说它们已经与事件处理代码分离开来。
也就是说,客户只用下命令,它不需要知道下令之后是如何完成了,只要达到接受者达到目的,并返回结果即可。
结构图
以大话设计模式例子为例:
client:客户只用知道有哪些命令就好了,客人只用知道有哪些烧烤,点菜就行,不需要知道烤烧烤的人是谁
Command:抽象出来的基类,包含一个接口execute和Receive,虽然客户不用知道是谁烤,但是每个烧烤店自己应该知道,每种烧烤谁负责
CrecreteCommand:实现具体的接口execute,这个接口就是调用Receive方法。
Receive:Receive相当于一个大厂库,为各种CrecuteCommand都有对应的方法
Invote:相当于服务员,收集这些请求,给Receive
代码实现如下:
#include<iostream>
#include<list>
using namespace std;
//Receiver定义
struct Receiver
{
// Receiver只做两件事情,分别定义接口
void muttonAction()
{
cout << "muttonAction" << endl;
}
void ChickenAction()
{
cout << "ChickenAction" << endl;
}
};
//所有的Command都由Receiver接收,所以Command必须知道Receiver是谁
//所以Command抽象类中包含一个recerver
struct Command
{
virtual void execute() = 0;
protected:
Receiver * recerver;
};
//recerver知道每种命令对应的Action,在具体Command中就调用了具体Action
struct MuttonCommand : Command
{
MuttonCommand(Receiver * recerver)
{
this->recerver = recerver;
}
virtual void execute()
{
this->recerver->muttonAction();
}
};
struct ChickenComand : Command
{
ChickenComand(Receiver * recerver)
{
this->recerver = recerver;
}
virtual void execute()
{
this->recerver->ChickenAction();
}
};
//Waiter只是一个中介,它等待客户下命令,然后把命令收集起来,交给Receiver
//实现了Receiver和客户之间分离
struct Waiter
{
void add(Command* com)
{
commandList.push_back(com);
}
void deleteCommand(Command* com)
{
commandList.remove(com);
}
void notify()
{
for(auto command : commandList)
{
command->execute();
}
}
private:
list<Command*> commandList;
};
int main()
{
//首先接受者申明
Receiver* rec = new Receiver();
//客户开始点菜
Command* com1 = new MuttonCommand(rec);
Command* com2 = new ChickenComand(rec);
//服务员收集所有菜
Waiter waiter;
waiter.add(com1);
waiter.add(com2);
//服务员通知接受者准备开始工作
waiter.notify();
delete rec;
delete com1;
delete com2;
return 0;
}
命令模式和代理模式的区别:
从使用角度上感觉这两种模式实现的功能很像。但从具体实现上来讲:
命令模式侧重点在于对命令的封装和对命令的管理,会把所有命令都封装起来,有一个中介去收集命令然后去给receive找相应的方法去做,对命令的发起者和命令的事件操作者之间解耦和。属于行为模式的一种。
而代理模式只是实现了实际可被访问功能的接口,代理模式并没有对命令或请求的管理。可以参考博文–代理模式。
命令模式优点:
1.设计命令队列
2.设置命令日志
3.接受者可以根据请求判断是否执行
4.可以实现撤销和重做