zoukankan      html  css  js  c++  java
  • Command Pattern -- 命令模式原理及实现(C++)

    主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》两本书。本文介绍命令模式的实现。

              

    What it is:Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

    将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。在OOP中,一切都是对象,将请求封装成对象,符合OOP的设计思想,当将客户的单个请求封装成对象以后,我们就可以对这个请求存储更多的信息,使请求拥有更多的能力;命令模式同样能够把请求发送者和接收者解耦,使得命令发送者不用去关心请求将以何种方式被处理。

    Command:声明执行操作的接口;
    ConcreteCommand:将一个接收者对象绑定于一个动作,之后,调用接收者相应的操作,以实现Execute来完成相应的命令;
    Client:创建一个具体命令对象,但是并没有设定它的接收者;
    Invoker:要求该命令执行这个请求;
    Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。

    以上这些对象是按照下面的方式进行协作的:

    1.Client创建一个ConcreteCommand命令对象,并指定它的Receiver对象;
    2.Invoker对象存储该ConcreteCommand对象;
    3.该Invoker通过调用Command对象的Execute操作来提交一个请求。如果这个命令请求是可以撤销的,ConcreteCommand就执行Execute操作之前存储当前状态以用于取消该命令请求;
    4.ConcreteCommand对象调用Receiver的一些操作以执行该请求。

    具体事例:

    我们去餐厅吃饭,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜,其实我们都不知道。抽象之,我们是“菜单请求者”,厨师是“菜单实现者”,2者之间是松耦合的,我们对这些菜的其他一些请求比如“撤销,重做”等,我们也不知道是谁在做。其实这就是本文要说的Command模式。将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。[GOF 《设计模式》]

    UML图如下:

    具体代码C++代码实现:

     1 #include <iostream>  
     2 #include <string>
     3 #include <vector>
     4 using namespace std;
     5 
     6 #define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
     7 9 10 /*烤肉师傅类,只负责烤串工作*/
    11 class Barbecuer
    12 {
    13 public:
    14     void BakeMutton(){cout<<"Bake mutton"<<endl;}
    15     void BakeChickenWing(){cout<<"Bake ChickenWing"<<endl;}
    16 };
    17 
    18 /*抽象命令类:是执行具体操作的接口*/
    19 class Command
    20 {
    21 public:
    22     Command(){}
    23     Command(Barbecuer *receiver):p_receiver(receiver){}
    24     virtual void ExecuteCommand() = 0; //执行命令
    25 protected:
    26     Barbecuer *p_receiver;
    27 };
    28 
    29 /*具体命令类:烤羊肉串命令*/
    30 class BakeMuttonCommand:public Command
    31 {
    32 public:
    33     BakeMuttonCommand(Barbecuer *receiver){p_receiver = receiver;}
    34     void ExecuteCommand(){p_receiver->BakeMutton();}
    35 };
    36 
    37 /*具体命令类:烤鸡翅串命令*/
    38 class BakeChickenWingCommand:public Command
    39 {
    40 public:
    41     BakeChickenWingCommand(Barbecuer *receiver){p_receiver = receiver;}
    42     void ExecuteCommand()
    43     {p_receiver->BakeChickenWing();}
    44 };
    45 
    46 /*服务员类*/
    47 class Waiter
    48 {
    49 public:
    50     void SetOrder(Command *command);
    51     void Notify();
    52 private:
    53     vector<Command *>p_commandList; //这里相当于一个命令对象队列
    54 };
    55 
    56 void Waiter::SetOrder(Command *command)
    57 {
    58     p_commandList.push_back(command);
    59     cout << "增加烤肉命令" << endl;
    60 }
    61 
    62 void Waiter::Notify()
    63 {
    64     vector<Command*>::iterator i;
    65     for(i = p_commandList.begin(); i != p_commandList.end(); ++ i)
    66         (*i)->ExecuteCommand();
    67 }
    68 
    69 int main(int argc, char *argv[])  
    70 {  
    71     //生成烤肉师傅、服务员、订单对象
    72     Barbecuer *p_cook = new Barbecuer();
    73     Command *p_mutton = new BakeMuttonCommand(p_cook);
    74     Command *p_chickenwing = new BakeChickenWingCommand(p_cook);
    75     Waiter *p_waiter = new Waiter();
    76 
    77     //将订单对象推送到命令队列
    78     p_waiter->SetOrder(p_mutton);
    79     p_waiter->SetOrder(p_chickenwing);
    80 
    81     //服务员通知烤肉师傅具体订单
    82     p_waiter->Notify();
    83 
    84     SAFE_DELETE(p_cook);
    85     SAFE_DELETE(p_mutton);
    86     SAFE_DELETE(p_chickenwing);
    87     SAFE_DELETE(p_waiter);
    88 
    89     return 0;  
    90 }
  • 相关阅读:
    Android——ArrayList 、LinkList、List 区别 & 迭代器iterator的使用 & HashMap、Hashtable、LinkedHashMap、TreeMap
    Android--List与ArrayList区别(转)
    android——inflater 用法(转)
    Android——列表视图 ListView(二)SimpleAdapter
    Odoo 仓库扫码打包方案
    Odoo 仓库调拨移动过程中 单位不允许错误的分析及解决方案
    Ubuntu FTP 配置
    attrs 中的 uid
    GitLab安装手记
    [转载]How To Add Swap on Ubuntu 12.04
  • 原文地址:https://www.cnblogs.com/lizhanwu/p/4435359.html
Copyright © 2011-2022 走看看