//+------------------------------------------------------------------+ //|                                                      Command.mqh | //|                                    2019-2020, dimitri pecheritsa | //|                                                792112@gmail.com | //+------------------------------------------------------------------+ //| command — behavioral design pattern                              | //+------------------------------------------------------------------+ //  design patterns: elements of reusable object-oriented software //  gof > erich gamma, richard helm, ralph johnson, john vlissides //  published — 1994 //+------------------------------------------------------------------+ //| intent                                                          | //+------------------------------------------------------------------+ //  encapsulate a request as an object //    thereby letting you parameterize clients with different requests //  queue or log requests, and support undoable operations //+------------------------------------------------------------------+ //| benefits                                                        | //+------------------------------------------------------------------+ //  variable aspect > when and how a request is fulfilled //  refactoring //      problems //        dependence on specific operations //        tight coupling //      solutions //        avoid hard-coded requests > also > chain of responsibility //        decouple with abstract coupling and layering //            also > abstract factory, bridge, chain of responsibility, //            facade, mediator, observer //+------------------------------------------------------------------+ //| applicability                                                    | //+------------------------------------------------------------------+ //  parameterize objects by an action to perform //  specify, queue, and execute requests at different times //      command is independent of the original request //  support undo //  support change log //      reapply after a system crash //      add load/store to command //      reload from disk //      reexecute with the execute //  structure a system around high-level operations //    built on primitives operations //+------------------------------------------------------------------+ //| structure                                                        | //+------------------------------------------------------------------+ // // |Client|      |Invoker|o------------------->| Command | //  |  |                                      |---------| //      |                                      |Execute()| //  |  +------->|Receiver|                        ^ //              |--------|      receiver          | //  |          |Action()|<--------------|  ConcreteCommand | //                                        |------------------| //  |                                    |Execute()        | //                                        | receiver.Action()| //  |                                    |------------------| //  + - - - - - - - - - - - - - - - - - >|state            | // #include <SRCPatternsPatternOrganizer.mqh> namespace Command { //+------------------------------------------------------------------+ //| participants > receiver                                          | //+------------------------------------------------------------------+ class Receiver //  knows how to perform the request operations //  any class may be a receiver   { public:                     Receiver(void);                     Receiver(Receiver&);   void              Action(void);   }; //+------------------------------------------------------------------+ //| participants > receiver > default                                | //+------------------------------------------------------------------+ Receiver::Receiver(void)   {   } //+------------------------------------------------------------------+ //| participants > receiver > copy constructor                      | //+------------------------------------------------------------------+ Receiver::Receiver(Receiver &src)   {   } //+------------------------------------------------------------------+ //| participants > receiver > action                                | //+------------------------------------------------------------------+ void Receiver::Action(void)   {   Print("receiver ",&this," action");   } //+------------------------------------------------------------------+ //| participants > command                                          | //+------------------------------------------------------------------+ class Command //  declares operation interface   { protected:   Receiver*        m_receiver; public:                     Command(Receiver*);                     ~Command(void);   virtual void      Execute(void)=0;   }; //+------------------------------------------------------------------+ //| participants > command > constructor                            | //+------------------------------------------------------------------+ Command::Command(Receiver* receiver)   {   m_receiver=new Receiver(receiver);   Print("receiver ",receiver," accepted by command ",&this);   } //+------------------------------------------------------------------+ //| participants > command > destructor                              | //+------------------------------------------------------------------+ Command::~Command(void)   {   if(CheckPointer(m_receiver)==1)     {       delete m_receiver;     }   } //+------------------------------------------------------------------+ //| participants > concrete command                                  | //+------------------------------------------------------------------+ class ConcreteCommand:public Command //  receiver/action binding //  implements execute() by calling receiver operation   { protected:   int              m_state; public:                     ConcreteCommand(Receiver*);   void              Execute(void);   }; //+------------------------------------------------------------------+ //| participants > concrete command > constructor                    | //+------------------------------------------------------------------+ ConcreteCommand::ConcreteCommand(Receiver* receiver):   Command(receiver),   m_state(0)   {   Print("command ",&this," state: ",m_state);   } //+------------------------------------------------------------------+ //| participants > concrete command > execute                        | //+------------------------------------------------------------------+ void ConcreteCommand::Execute(void)   {   Print("command executes receiver ",m_receiver);   m_receiver.Action();   m_state=1;   Print("command ",&this," state: ",m_state);   } //+------------------------------------------------------------------+ //| participants > invoker                                          | //+------------------------------------------------------------------+ class Invoker //  asks the command to carry out the request   { public:                     ~Invoker(void);   void              StoreCommand(Command*);   void              Execute(void); protected:   Command*          m_command;   }; //+------------------------------------------------------------------+ //| participants > invoker > destructor                              | //+------------------------------------------------------------------+ Invoker::~Invoker(void)   {   if(CheckPointer(m_command)==1)     {       delete m_command;     }   } //+------------------------------------------------------------------+ //| participants > invoker > command                                | //+------------------------------------------------------------------+ void Invoker::StoreCommand(Command* command)   {   m_command=command;   Print("command ",m_command," stored");   } //+------------------------------------------------------------------+ //| participants > invoker > execute                                | //+------------------------------------------------------------------+ void Invoker::Execute(void)   {   Print("executing command ",m_command);   m_command.Execute();   } //+------------------------------------------------------------------+ //| participants > client                                            | //+------------------------------------------------------------------+ class Client:public ClientExample //  creates a concrete command object and sets its receiver   { public:   string            Output(void);   void              Run(void);   }; string Client::Output(void)   {   return __FUNCTION__;   } //+------------------------------------------------------------------+ //| collaborations                                                  | //+------------------------------------------------------------------+ void Client::Run(void) //  client //      creates a concrete command //      specifies its receiver //  invoker //      stores the concrete command requests by calling execute() //      command undoable //        concrete command stores state prior to execute() // //  aReceiver  aClient                    aCommand      anInvoker //      |          |                          |              | //      |          |                                          | //      |        | |newCommand(aReceiver)    |              | //      |        | |- - - - - - - - - - - ->| |              | //      |        | |                        |              | //      |        | |StoreCommand(aCommand)  |              | //      |        | |-------------------------|------------->| | //      |          |                          |              | | //      |          |                          |              | //      /          /                          /              / //      /          /                          /              / //      |          |                          |              | //      |          |                          |    Execute()| | //      |          |                Action()| |<------------| | //      | |<--------|-------------------------| |            | | //      |          |                          |              |   {   Receiver receiver;   Invoker invoker;   invoker.StoreCommand(new ConcreteCommand(&receiver));   invoker.Execute();   } } //+------------------------------------------------------------------+ //| output                                                          | //+------------------------------------------------------------------+ //  Command::Client::Output //  receiver 2097152 accepted by command 4194304 //  command 4194304 state: 0 //  command 4194304 stored //  executing command 4194304 //  command executes receiver 5242880 //  receiver 5242880 action //  command 4194304 state: 1 //+------------------------------------------------------------------+ //| consequences                                                    | //+------------------------------------------------------------------+ //  decouple operation's caller/performer //  commands are first-class manipulateable/extendable objects //  assemble commands into a composite command //  easy to add new commands //+------------------------------------------------------------------+ //| implementation                                                  | //+------------------------------------------------------------------+ //  how intelligent is a command //      binds receiver/actions //      delegates nothing to receiver //        commands are independent of the existing classes //        no receiver exists //        command knows receiver //      commands can find receiver dynamically //  undo and redo //      concrete command stores additional state //        receiver //        operation arguments //        receiver's original values that can change receiver //        provides the recover operations //      multiple-level //        history list of sequences of commands //        reverse-execute to cancel //        maybe copy an undoable command before putting it on list //  error accumulation in undo //      delay can be a problem //      errors can accumulate //      use memento to store more original state in the command //      for recover //  templates for non-undoable/no argument commands //+------------------------------------------------------------------+ //| related patterns                                                | //+------------------------------------------------------------------+ //  composite > implement macrocommands //  memento > keep state the command requires to undo its effect //  prototype > a command that must be copied //    before being placed on the history list //+------------------------------------------------------------------+