命令模式
理论
命令模式(Command),将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式的优点:
1. 能较容易地设计一个命令队列;
2. 比较容易地将命令记入日志;
3. 允许接受请求地一方决定是都要否决要求;
4. 可以容易地实现对请求地撤销和重做;
5. 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。
实例
模拟路边烤肉串:‘行为请求者’与‘行为实现者’的紧耦合
店内烤肉串:‘行为请求者’与‘行为实现者’的松耦合
UML类图
紧耦合设计:
客户端程序与烤肉串者紧耦合,尽管简单,但却极为僵化,有很多的隐患。在用户多,请求多的时候就容易乱。
送耦合设计:命令模式
代码实现
#include <iostream> #include <list> using namespace std; //烤羊肉者 Receiver类 class Barbecuer { public: void BakeMutton() { cout << "烤羊肉串!" << endl; } void BakeChickenWing() { cout << "烤鸡翅!" << endl; } }; //抽象命令类 class Command { public: Command(Barbecuer* receiver) { this->receiver = receiver; } virtual void ExcuteCommand() {} protected: Barbecuer* receiver; }; //具体命令类 class BakeMuttonCommand :public Command { public: BakeMuttonCommand(Barbecuer* receiver) :Command(receiver) {} void ExcuteCommand() { receiver->BakeMutton(); } }; class BakeChickenWingCommand :public Command { public: BakeChickenWingCommand(Barbecuer* receiver) :Command(receiver) {} void ExcuteCommand() { receiver->BakeChickenWing(); } }; //服务员 Invoker类 //只记录了一个命令 class Waiter { public: //设置订单 void SetOrder(Command* command) { this->command = command; } //通知执行 void Notify() { command->ExcuteCommand(); } private: Command* command; }; //维护一个命令队列,实现命令的添加、撤销、执行 class WaiterList { public: void addCommand(Command* command){ if (typeid(*command) == typeid(BakeChickenWingCommand)){ cout << "服务员:鸡翅没有了,请点别的烧烤。" << endl; } else { commandList.push_back(command); cout << "增加订单: 烤羊肉" << endl; } } void cancelCommand(Command* command){ commandList.remove(command); } void Notify() { for (Command* cmd : commandList){ cout << endl; cout << "目前订单:" << endl; cmd->ExcuteCommand(); } } private: list<Command*> commandList; }; int main() { //开店前准备 Barbecuer* boy = new Barbecuer(); Command* bakeMuttonCommand1 = new BakeMuttonCommand(boy); Command* bakeMuttonCommand2 = new BakeMuttonCommand(boy); Command* bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); Waiter girl; //开店营业 girl.SetOrder(bakeMuttonCommand1); girl.Notify(); girl.SetOrder(bakeMuttonCommand2); girl.Notify(); girl.SetOrder(bakeChickenWingCommand1); girl.Notify(); cout << "--------------------------------" << endl; WaiterList girl2; girl2.addCommand(bakeMuttonCommand1); girl2.addCommand(bakeMuttonCommand2); girl2.addCommand(bakeChickenWingCommand1); girl2.cancelCommand(bakeMuttonCommand2); girl2.Notify(); delete boy; delete bakeMuttonCommand1; delete bakeMuttonCommand2; delete bakeChickenWingCommand1; return 0; }
运行结果: