命令模式 X 可撤销的操作 X 改善容易混乱的命令

  1. #include <iostream.h>
  2. class Reciver
  3. //与ConcreteCommand类是关联关系,实心箭头表示,被指向
  4. {
  5. public:
  6.     void Action()
  7.     {
  8.         cout<<"Reciver action";
  9.     }
  10. };
  11. class Command
  12. {
  13. protected:
  14.     Reciver* pReciver;
  15. public:
  16.     Command(Reciver* p) : pReciver(p) {}
  17.     virtual void Execute()=0;
  18. };
  19. class ConcreteCommand : public Command
  20. //本类和Receiver是关联关系,实心箭头指向Receiver类。
  21. //Receiver指针保存在基类中,可以通过它调用Receiver对象的函数。
  22. {
  23. public:
  24.     //继承,将reciver保存起来,在基类中
  25.     ConcreteCommand(Reciver* r) : Command(r) {  }
  26.     //继承,具体实现Execute接口
  27.     void Execute()
  28.     {
  29.         pReciver->Action();
  30.     }
  31. };
  32. class Invoker
  33. {
  34. private:
  35.     //聚合Command类,菱形加实心箭头表示;private成员(因为子类不需要用到这个Invoker的成员)
  36.     Command* pCommand;
  37. public:
  38.     void SetCommand(Command* p)
  39.     {
  40.         pCommand = p;
  41.     }
  42.     void ExecuteCommand()
  43.     {
  44.         pCommand->Execute();
  45.     }
  46. };
  47. void main()
  48. {
  49.     //客户端代码,创建一个具体命令对象并设定它的接收者
  50.     Reciver* r = new Reciver();
  51.     Command* c = new ConcreteCommand(r);
  52.     Invoker* i =new Invoker();
  53.     i->SetCommand(c);
  54.     i->ExecuteCommand();
  55. };

        以上是命令模式的基本实现框架代码。

       “行为请求者”与“行为实现者”的紧耦合。

       对请求排队或记录请求日志,以及支持可撤销的操作等行为时,“行为请求者”与“行为实现者”的紧耦合是不合适的。

       利用一个服务员来解耦客户和烤肉师傅的处理。

    现实代码的坏味道:

    由于客户和小摊烤羊肉串老板的紧耦合,所以使得容易出错、容易混乱,也容易挑剔。因为客户站在那里都盯着烤肉,烤得好坏清清楚楚、挑剔也接踵而至。

       命令模式的优点:

1,  能较容易地设计一个命令队列;

2,  在需要的情况下,可以较容易地将命令记入日志;

3,  允许接收请求 一方决定是否要否决请求;

4,  可以容易地实现对请求的撤销和重做;

5,  由于加进心得具体命令类不影响其他的类,因此增加新的具体命令类很容易。

关键:命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。

注意:只有在真正需要如撤销、恢复等操作功能的时候,将原来的代码重构为命令模式才有意义。

 

下面是第二个版本的具体实现代码:

  1. #include <iostream>
  2. using namespace std;
  3. class Barbecuer
  4. {
  5. public:
  6.     void BakeMutton()
  7.     {
  8.         cout<<"烤羊肉串ing"<<endl;
  9.     }
  10.     void BakChickenWing()
  11.     {
  12.         cout<<"烤鸡翅ing"<<endl;
  13.     }
  14. };
  15. //抽象命令类
  16. class Command
  17. {
  18. protected:
  19.     Barbecuer* pReciver;
  20. public:
  21.     Command(Barbecuer* p) : pReciver(p){ }
  22.     virtual void ExecuteCommand()=0;
  23. };
  24. //具体命令类,继承
  25. class BakeMuttonCommand : public Command
  26. {
  27. public:
  28.     BakeMuttonCommand(Barbecuer* reciver) : Command(reciver){   }
  29.     //在这个类中,依赖于Bakebecuer类的具体操作实现
  30.     virtual void ExecuteCommand()
  31.     {
  32.         pReciver->BakeMutton();
  33.     }
  34. };
  35. //本类的关系说明类似于BakeMuttonCommand类
  36. class BakeChickenWingCommand : public Command
  37. {
  38. public:
  39.     BakeChickenWingCommand(Barbecuer* reciver) : Command(reciver){  }
  40.     virtual void ExecuteCommand()
  41.     {
  42.         pReciver->BakChickenWing();
  43.     }
  44. };
  45. class Waiter
  46. //服务员类与Command类是聚合关系;当“通知”的时候,发生的实际执行操作,仍然是在Command类中进行的
  47. //就像“雁群”的飞行,实际调用的时候,仍然是一只只大雁调用自己的“飞行”函数。
  48. {
  49. private:
  50.     Command* pCommand;
  51. public:
  52.     //设置订单
  53.     void setOrder(Command* p)
  54.     {
  55.         pCommand=p;
  56.     }
  57.     //通知执行
  58.     void Notify()
  59.     {
  60.         pCommand->ExecuteCommand();
  61.     }
  62. };
  63. void main()
  64. {
  65.     Barbecuer* boy = new Barbecuer();
  66.     Command* pBakeMuttonCommand1 = new BakeMuttonCommand(boy);
  67.     Command* pBakeMuttonCommand2 = new BakeMuttonCommand(boy);
  68.     Command* pBakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
  69.     Waiter* girl = new Waiter();
  70.     
  71.     girl->setOrder(pBakeChickenWingCommand1);
  72.     girl->Notify();
  73.     girl->setOrder(pBakeMuttonCommand2);
  74.     girl->Notify();
  75.     girl->setOrder(pBakeChickenWingCommand1);
  76.     girl->Notify();
  77. };

    当需要用到撤销、重复、记录日志等命令的时候,我们需要重构相应的代码以实现具体功能——现在看来,比较简单了。下面是代码的第三个版本,重点在于重新实现了Waiter类:很显然,对订单的操作,是应该加给他的功能。

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. class Barbecuer
  5. {
  6. public:
  7.     void BakeMutton()
  8.     {
  9.         cout<<"烤羊肉串ing"<<endl;
  10.     }
  11.     void BakChickenWing()
  12.     {
  13.         cout<<"烤鸡翅ing"<<endl;
  14.     }
  15. };
  16. //抽象命令类
  17. class Command
  18. {
  19. protected:
  20.     Barbecuer* pReciver;
  21. public:
  22.     Command(Barbecuer* p) : pReciver(p){ }
  23.     virtual void ExecuteCommand()=0;
  24. };
  25. //具体命令类,继承
  26. class BakeMuttonCommand : public Command
  27. {
  28. public:
  29.     BakeMuttonCommand(Barbecuer* reciver) : Command(reciver){   }
  30.     //在这个类中,依赖于Bakebecuer类的具体操作实现
  31.     virtual void ExecuteCommand()
  32.     {
  33.         pReciver->BakeMutton();
  34.     }
  35. };
  36. //本类的关系说明类似于BakeMuttonCommand类
  37. class BakeChickenWingCommand : public Command
  38. {
  39. public:
  40.     BakeChickenWingCommand(Barbecuer* reciver) : Command(reciver){  }
  41.     virtual void ExecuteCommand()
  42.     {
  43.         pReciver->BakChickenWing();
  44.     }
  45. };
  46. class Waiter
  47. //服务员类与Command类是聚合关系;当“通知”的时候,发生的实际执行操作,仍然是在Command类中进行的
  48. //就像“雁群”的飞行,实际调用的时候,仍然是一只只大雁调用自己的“飞行”函数。
  49. {
  50. private:
  51.     vector<Command*> orders;
  52. public:
  53.     //设置订单
  54.     void setOrder(Command* p)
  55.     {
  56.         orders.push_back(p);
  57.     }
  58.     void cancelOrder(Command* p)
  59.     {
  60.         //如果满足条件,则删除订单
  61.         if (1)
  62.         {
  63.             orders.pop_back();
  64.         }       
  65.     }
  66.     //通知执行
  67.     void Notify()
  68.     {
  69.         for (vector<Command*>::iterator it=orders.begin(); it!=orders.end();it++)
  70.         {
  71.             (*it)->ExecuteCommand();
  72.         }
  73.     }
  74. };
  75. void main()
  76. {
  77.     Barbecuer* boy = new Barbecuer();
  78.     Command* pBakeMuttonCommand1 = new BakeMuttonCommand(boy);
  79.     Command* pBakeMuttonCommand2 = new BakeMuttonCommand(boy);
  80.     Command* pBakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
  81.     
  82.     Waiter* girl = new Waiter();
  83.     
  84.     girl->setOrder(pBakeChickenWingCommand1);
  85.     girl->setOrder(pBakeMuttonCommand2);
  86.     girl->setOrder(pBakeChickenWingCommand1);
  87.     girl->Notify();
  88. };

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值