Expert Advisors • Indicators • Scripts • Libraries

MQL.RobotFX.org is the biggest collection of MetaTrader expert advisors (MT5 & MT4), indicators, scripts and libraries that can be used to improve trading results, minimize risks or simply automate trading tasks

MetaTrader 5 Libraries | Command - behavioral design pattern

MetaTrader Experts, Indicators, Scripts and Libraries
//+------------------------------------------------------------------+  //|                                                      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 <SRC\Patterns\PatternOrganizer.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  //+------------------------------------------------------------------+  
31361