定义
命令模式(Command Pattern)是一种行为设计模式,它将请求或操作封装为一个对象,从而使你可以将请求发送者与请求接收者解耦。这种模式提供了一个对象来表示要执行的命令,并允许你在不暴露请求细节的情况下参数化对象,支持撤销操作以及对命令的排队和日志记录等功能。
结构
-
命令接口(Command) :声明一个执行操作的接口。
-
具体命令(ConcreteCommand) :实现
Command接口,定义与接收者的绑定,并调用接收者的相应操作。 -
接收者(Receiver) :实际执行命令的对象。知道如何实现与执行相关的操作。
-
调用者(Invoker) :要求执行一个命令。它保持对命令对象的引用,并在需要时调用命令对象的
execute方法。
优点
-
解耦:将请求发起者与请求接收者解耦。调用者只知道命令接口,不需要知道接收者的细节。
-
灵活性:可以容易地增加新的命令,而不需要改变现有的代码。
-
撤销操作:可以实现撤销功能,记录执行的命令并允许回滚。
-
命令参数化:可以将请求参数化为对象,实现排队、日志记录等功能。
代码示例
饭店点菜流程的简单实现,服务员记录顾客点的菜品,并向厨师发送做菜命令。
#include <iostream>
#include <vector>
// 接收者:厨师类
class Cooker
{
public:
// 麻婆豆腐
void cookTofu()
{
std::cout << "麻婆豆腐出锅" << std::endl;
}
// 烤鱼
void cookFish()
{
std::cout << "烤鱼出锅" << std::endl;
}
};
// 抽象命令类
class Command
{
protected:
Cooker* receiver;
public:
Command(Cooker* receiver) : receiver(receiver) {}
// 执行命令
virtual void excuteCommand() = 0;
};
// 具体命令1:制作麻婆豆腐
class TofuCommand : public Command
{
public:
TofuCommand(Cooker* receiver) : Command(receiver) {}
void excuteCommand() override
{
receiver->cookTofu();
}
};
// 具体命令2:制作烤鱼
class FishCommand : public Command
{
public:
FishCommand(Cooker* receiver) : Command(receiver) {}
void excuteCommand() override
{
receiver->cookFish();
}
};
// 调用者:服务员类
class Waiter
{
private:
std::vector<Command*> orders;
public:
// 设置订单
void setOrder(Command* command)
{
orders.push_back(command);
}
// 通知执行
void notifyCommand()
{
for (const auto& it : orders)
{
it->excuteCommand();
}
}
};
int main()
{
Cooker cooker;
Waiter waiter;
// 创建具体命令
Command* cmd1 = new TofuCommand(&cooker);
Command* cmd2 = new TofuCommand(&cooker);
Command* cmd3 = new TofuCommand(&cooker);
Command* cmd4 = new FishCommand(&cooker);
Command* cmd5 = new FishCommand(&cooker);
//设置订单
waiter.setOrder(cmd1);
waiter.setOrder(cmd2);
waiter.setOrder(cmd3);
waiter.setOrder(cmd4);
waiter.setOrder(cmd5);
// 执行命令
waiter.notifyCommand();
system("pause");
return 0;
}
```cpp