今天写一下《大话设计模式》第23个设计模式 - - 命令模式,先贴下代码:
头文件:
1 #ifndef _COMMAND_PATTERN_
2 #define _COMMAND_PATTERN_
3
4 class Barbecuer
5 {
6 public:
7 void BakeChickenWing() { std::cout << "BakeChickenWing" << std::endl; }
8 void BakeMutton () { std::cout << "BakeMutton" << std::endl; }
9 };
10
11 class Command
12 {
13 public:
14 virtual void DoCmd () = 0;
15 protected:
16 Barbecuer Baker;
17 };
18
19 class CommandBakeChicken : public Command
20 {
21 public:
22 void DoCmd ()
23 {
24 Baker.BakeChickenWing ();
25 }
26 };
27
28 class CommandBakeMutton : public Command
29 {
30 public:
31 void DoCmd ()
32 {
33 Baker.BakeMutton ();
34 }
35 };
36 class Waiter
37 {
38 public:
39 void AddCmd (Command *cmd)
40 {
41 cmds.push_back(cmd);
42 }
43 void RemoveCmd (Command *cmd);
44 void NotifyCmds ();
45 private:
46 std::vector<Command *> cmds;
47 };
48 #endif
源文件:
1 #include <iostream>
2 #include <vector>
3 #include "cmdPattern.h"
4 using namespace std;
5
6 void Waiter::NotifyCmds ()
7 {
8 vector<Command *>::iterator iter = cmds.begin();
9 while ( iter != cmds.end())
10 {
11 (*iter)->DoCmd ();
12 ++iter;
13 }
14 }
15
16 void Waiter::RemoveCmd (Command *cmd)
17 {
18 vector<Command *>::iterator iter = cmds.begin();
19 while (iter != cmds.end())
20 {
21 if (*iter == cmd)
22 iter = cmds.erase (iter);
23 else
24 ++iter;
25 }
26 }
27 int main(void)
28 {
29 Barbecuer boy;
30 Waiter waiter;
31 Command *pBakeMut = new CommandBakeMutton;
32 waiter.AddCmd (pBakeMut);
33 Command *pBakeChk = new CommandBakeChicken;
34 waiter.AddCmd (pBakeChk);
35 Command *pBakeMut2 = new CommandBakeMutton;
36 waiter.AddCmd (pBakeMut2);
37 waiter.NotifyCmds ();
38 waiter.RemoveCmd (pBakeMut);
39 waiter.NotifyCmds ();
40 return 0;
41 }
从代码中看到,类Barbecuer(烤肉者)只提供了具体的动作实现,比如烤羊肉,烤鸡肉。此类不直接和客户打交道。而是由服务员类来直接下发命令给它。
Waiter类通过AddCmd() 增加一条命令,RemoveCmd()方法取消一条命令,然后通过NotifyCmds()方法来调用每条命令中的Docmd()方法。Docmd()方法是在Command类中实现的抽象方法,由它的继承者区分实现不同的方法。
Command类的处理是采用提取一个抽象的类,然后通过继承的方式实现了各个具体命令的执行类。这样做的好处是如果以后要提供其他的命令支持,只需要添加一个具体的子类就可以了。比如,如果要实现烤鱼这个功能,那么只需要增加一个具体的烤鱼类,比较灵活方便,Waiter类的处理不需要变化。
因为Command类是具体的调用Barbecuer方法的,所以需要持有(依赖于)Barbecuer对象。