介绍
- Receive接收者角色
该角色就是干活的角色, 命令传递到这里是应该被执行的。作为抽象类,定义一个可接受消息的抽象类,从而保证多个不同的具体角色均可接受命令 - Command命令角色
需要执行的所有命令都在这里声明。定义抽象类一个和一系列具体命令类,每个类对应一个命令。 - Invoker调用者角色
接收到命令, 并执行命令。
优点:类间解耦、可扩展性 、命令模式结合其他模式会更优秀
缺点: 如果有N个命令, Command的子类就是N个
UML类图:
简单示例:
#ifndef SIMPLE_COMMAND_H
#define SIMPLE_COMMAND_H
#include <iostream>
using namespace std;
/**
* @brief The Receiver class
* Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。
*/
class Receiver
{
public:
void action()
{
cout<<"执行请求!"<<endl;
}
};
/**
* @brief The Command class
* Command类,用来声明执行操作的接口。
*/
class Command
{
public:
Command(Receiver * receiver)
{
m_receiver = receiver;
}
virtual void execute() = 0;
protected:
Receiver *m_receiver;
};
/**
* @brief The ConcreteCommand class
* ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute。
*/
class ConcreteCommand : public Command
{
public:
ConcreteCommand(Receiver *receiver)
:Command(receiver)
{
}
void execute() override
{
cout<<"ConcreteCommand:\n";
m_receiver->action();
}
};
/**
* @brief The Invoker class
* Invoker类,要求该命令执行这个请求。
*/
class Invoker
{
public:
void setCommand(Command *command)
{
m_command = command;
}
void executeCommand()
{
m_command->execute();
}
private:
Command *m_command;
};
#endif // SIMPLE_COMMAND_H
大话设计模式第23章烧烤摊:(最近地摊经济挺火的)
UML类图:
代码:
#ifndef BARBECUE_COMMAND_H
#define BARBECUE_COMMAND_H
#include <iostream>
#include <list>
#include <ctime>
using namespace std;
/**
* @brief The Barbecuer class
* 烤肉师
*/
class Barbecuer
{
public:
void BakeMutton()
{
cout<<"烤羊肉串!"<<endl;
}
void BakeChickenWing()
{
cout<<"烤鸡翅!"<<endl;
}
};
/**
* @brief The Command class
* 抽象命令类
*/
class Command
{
public:
Command(Barbecuer *receiver)
{
m_receiver = receiver;
}
void setCmd(string strCmd)
{
m_strCmd = strCmd;
}
string getCmdString() const
{
return m_strCmd;
}
virtual void excuteCommand() = 0;
protected:
Barbecuer *m_receiver;
string m_strCmd;
};
/**
* @brief The BakeMuttonCommand class
* 烤肉命令
*/
class BakeMuttonCommand : public Command
{
public:
BakeMuttonCommand(Barbecuer *receiver)
:Command(receiver)
{
m_strCmd = "烤羊肉串";
}
void excuteCommand() override
{
m_receiver->BakeMutton();
}
};
/**
* @brief The BakeChickenWingCommand class
* 烤鸡翅命令
*/
class BakeChickenWingCommand : public Command
{
public:
BakeChickenWingCommand(Barbecuer *receiver)
:Command(receiver)
{
m_strCmd = "烤鸡翅";
}
void excuteCommand() override
{
m_receiver->BakeChickenWing();
}
};
/**
* @brief The Waiter class
* 服务员
*/
class Waiter
{
public:
Waiter()
{
m_list.clear();
}
void setOrder(Command *cmd)
{
m_list.push_back(cmd);
// 基于当前系统的当前日期/时间
time_t now = time(0);
// 把 now 转换为字符串形式
char* dt = ctime(&now);
cout<<"增加订单:"<<cmd->getCmdString()<<"时间:"<< dt << endl;
}
void cancelOrder(Command *cmd)
{
m_list.remove(cmd);
// 基于当前系统的当前日期/时间
time_t now = time(0);
// 把 now 转换为字符串形式
char* dt = ctime(&now);
cout<<"取消订单:"<<cmd->getCmdString()<<"时间:"<< dt << endl;
}
void notify()
{
for (list<Command*>::iterator it = m_list.begin(); it != m_list.end(); it++) {
(*it)->excuteCommand();
}
}
private:
list<Command*> m_list;
};
#endif // BARBECUE_COMMAND_H
总结:(来自大话设计模式)
第一,它能较容易地设计一一个命令队列;
第二,在需要的情况下,可以较容易地将命令记入日志;
第三,允许接收请求的一方决定是否要否决请求。”
第四,可以容易地实现对请求的撤销和重做;
第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。其实还有最关键的优点就是命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。[DP]