当你投递快递时,是否想过它会怎么被寄到目的地?空运还是海运?这些我们都不关心,只要你的快递有人运送就行。
假设有个接待员来接收你的快递,他可以视为一个Invoker,他的executeCommand方法保证快递正常运送:
- class Invoker
- {
- public:
- void setCommand(Command* pCommand) : mpCommand(pCommand) {}
- void executeCommand() { mpCommand->execute(); }
- private:
- Command* mpCommand;
- };
setCommand的作用是选择快递公司。快递公司就是一个Command,通过execute方法来运送快递:
- class Command
- {
- public:
- virtual void execute() = 0;
- virtual void setReceiver(Receiver) = 0;
- };
你关心的只是哪个快递公司,但它怎么运送,是快递公司的事,你不需要知道。
收件人是一个Receiver:
- class Receiver
- {
- public:
- void action();
- };
你,作为上帝,就是Client:
- class Client
- {
- public:
- void post()
- {
- Invoker invoker;
- invoker.setCommand(new SomeCommand(SomeReceiver));
- invoker.executeCommand();
- }
- };
你告诉接待员你要哪家快递公司,收件人是谁,然后让他就把快递邮出去。
命令模式的魅力在于Client可以自由选择Command和Receiver,而且Invokder根本就不用了解Command的细节,只需做一个简单的转接。这样接待员的工作才会相当轻松,否则接待员可能需要千里迢迢拔山涉水拿着你的包裹送给收件人,相当杯具……
Invoker可以接收多个Command,这些Command也可以来自不同的Client,所以Invoker也可以这样:
- class Invoker
- {
- public:
- void setCommand(Id);
- void executeCommand(Id);
- };
有时我们可能需要一个叫宏命令的东西,它本身是个Command,但是可以把其它一些命令聚合起来一起执行:
- class MacroCommand : public Command
- {
- public:
- Command(Command[] commands) {}
- virtual void execute()
- {
- foreach(Command* pCommand in commands)
- pCommand->execute();
- }
- };
Command还有一个很重要的特性,那就是undo:
- class Command
- {
- public:
- virtual void execute() = 0;
- virtual void undo() = 0;
- };
Command还可以存储起来,比如服务器突然死机重启后,客户端发过来的Command不会被丢失,仍然会被执行。
- class Command
- {
- public:
- virtual void execute() = 0;
- virtual void undo() = 0;
- virtual void store() = 0;
- virtual void load() = 0;
- };
阅读(844) | 评论(0) | 转发(0) |