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 | Chain of responsibility - behavioral design pattern

MetaTrader Experts, Indicators, Scripts and Libraries
//+------------------------------------------------------------------+  //|                                        ChainOfResponsibility.mqh |  //|                                    2019-2020, dimitri pecheritsa |  //|                                                 792112@gmail.com |  //+------------------------------------------------------------------+  //| chain of responsibility — behavioral design pattern              |  //+------------------------------------------------------------------+  //   design patterns: elements of reusable object-oriented software  //   gof > erich gamma, richard helm, ralph johnson, john vlissides  //   published — 1994  //+------------------------------------------------------------------+  //| intent                                                           |  //+------------------------------------------------------------------+  //   avoid coupling the sender of a request to its receiver  //    by giving more than one object a chance to handle the request  //   chain the receiving objects and pass the request along the chain  //    until an object handles it  //+------------------------------------------------------------------+  //| benefits                                                         |  //+------------------------------------------------------------------+  //   aspect that may vary > object that can fulfill a request  //   code refactoring  //      problems  //         dependence on specific operations  //         tight coupling  //         extending functionality by subclassing  //      solutions  //         avoid — hard-coded requests  //            also > command  //         decouple — with abstract coupling and layering  //            also > abstract factory, bridge, command, facade,   //             mediator, observer  //         use composition/delegation — for combining behavior  //            also > bridge, composite, decorator, observer, strategy  //+------------------------------------------------------------------+  //| applicability                                                    |  //+------------------------------------------------------------------+  //   more than one object may handle a request,  //    and the handler isn't known a priori  //      the handler should be ascertained automatically  //   you want to issue a request to one of several objects  //    without specifying the receiver explicitly  //   the set of objects that can handle a request  //    should be specified dynamically  //+------------------------------------------------------------------+  //| structure                                                        |  //+------------------------------------------------------------------+  //  //                                        +----------------+  //                                        |                |  //                                        v     successor  |  //      |Client|------------>|    Handler    |-------------+  //                           |---------------|  //                           |HandleRequest()|  //                                   ^  //                                   |  //                      +------------+-------------+  //                      |                          |  //             |ConcreteHandler1|         |ConcreteHandler2|  //             |----------------|         |----------------|  //             |HandleRequest() |         |HandleRequest() |  //  //+------------------------------------------------------------------+  //| a typical object structure                                       |  //+------------------------------------------------------------------+  //  //   |aClient    |  //   |-----------|      |aConcreteHandler|  //   |aHandler *-|----->|----------------|       |aConcreteHandler|  //                      |successor     *-|------>|----------------|  //                                               |successor       |  //  #include <SRC\Patterns\PatternOrganizer.mqh>  namespace ChainOfResponsibility  {  //+------------------------------------------------------------------+  //| participants > handler                                           |  //+------------------------------------------------------------------+  class Handler  //   defines an interface for handling requests  //   (optional) implements the successor link    {  public:     Handler*          successor;     virtual void      HandleRequest(int)=0;                      ~Handler(void);    };  //+------------------------------------------------------------------+  //| participants > handler > destructor                              |  //+------------------------------------------------------------------+  Handler::~Handler(void)    {     delete successor;    }  //+------------------------------------------------------------------+  //| participants > concrete handler                                  |  //+------------------------------------------------------------------+  //   handles requests it is responsible for  //   can access its successor  //   if the concretehandler can handle the request, it does so  //    else it forwards the request to its successor  //+------------------------------------------------------------------+  //| participants > concrete handler > 1                              |  //+------------------------------------------------------------------+  class ConcreteHandler1:public Handler    {  public:     void              HandleRequest(int);    };  //+------------------------------------------------------------------+  //| participants > concrete handler > 1 > handle request             |  //+------------------------------------------------------------------+  void ConcreteHandler1::HandleRequest(int request)    {     if(request==1)        Print("request: ",request,". response: one. handled by: ",&this);     else        if(CheckPointer(successor))          {           Print("request: ",request,". cannot be handled by ",&this,", forwarding to successor...");           successor.HandleRequest(request);          }    }  //+------------------------------------------------------------------+  //| participants > concrete handler > 2                              |  //+------------------------------------------------------------------+  class ConcreteHandler2:public Handler    {  public:     void              HandleRequest(int);    };  //+------------------------------------------------------------------+  //| participants > concrete handler > 2 > handle request             |  //+------------------------------------------------------------------+  void ConcreteHandler2::HandleRequest(int request)    {     if(request==2)        Print("request: ",request,". response: two. handled by: ",&this);     else        if(CheckPointer(successor))          {           Print("request: ",request,". cannot be handled by ",&this,", forwarding to successor...");           successor.HandleRequest(request);          }    }  //+------------------------------------------------------------------+  //| participants > client                                            |  //+------------------------------------------------------------------+  class Client:public ClientExample  //   initiates the request to a concrete handler on the chain    {  public:     string            Output();     void              Run();    };  string Client::Output()    {     return __FUNCTION__;    }  //+------------------------------------------------------------------+  //| collaborations                                                   |  //+------------------------------------------------------------------+  void   Client::Run()  //   request is sent along the chain until concrete handler handles it    {     Handler* h1=new ConcreteHandler1();     Handler* h2=new ConcreteHandler2();     h1.successor=h2;     h1.HandleRequest(1); // will handle the request     h1.HandleRequest(2); // will pass the request to successor  //---     delete h1;    }  }  //+------------------------------------------------------------------+  //| output                                                           |  //+------------------------------------------------------------------+  //   ChainOfResponsibility::Client::Output  //   request: 1. response: one. handled by: 2097152  //   request: 2. cannot be handled by 2097152, forwarding to successor...  //   request: 2. response: two. handled by: 3145728  //+------------------------------------------------------------------+  //| consequences                                                     |  //+------------------------------------------------------------------+  //   reduced coupling  //      object does not know who handles a request  //      object knows that a request will be handled  //      sender does not know receiver  //      object does not know the chain structure  //      simple object interconnections  //      objects do not maintain references to all candidate receivers  //      objects keep a reference to successor only  //   flexibility in assigning responsibilities to objects  //      add/change the chain at run-time  //       combine with subclassing to specialize handlers statically  //   receipt isn't guaranteed  //      request has no explicit receiver  //      request can fall off the end of the chain  //      also when the chain is not configured properly  //+------------------------------------------------------------------+  //| implementation                                                   |  //+------------------------------------------------------------------+  //   successor chain  //      define new links  //      use existing links when the links support the chain  //         saves from defining links explicitly  //         saves space  //         if other structure then define redundant links  //   connecting successors  //      if no preexisting references for defining a chain  //       then handler defines the interface, maintains the successor  //       handler provides a default implementation of handlerequest  //       concrete handler doesn't have to override the forwarding operation  //   representing requests  //      request is a hard-coded operation call  //      convenient and safe  //      can forward only handler's fixed set of requests  //      or use a single handler function with request code as a parameter  //      supports an open-ended requests  //      sender/receiver must agree on encoding  //      requires conditional statements for dispatching the request  //      less safe than direct call  //      can use separate requests that bundle parameters  //      request can represent requests explicitly  //      can subclass new requests  //      subclasses can define different parameters  //      handlers must know the kind of request  //      identify the request by accessor function — returns class id  //      or receiver can use run-time type information  //+------------------------------------------------------------------+  //| related patterns                                                 |  //+------------------------------------------------------------------+  //   composite > component's parent can act as its successor  //+------------------------------------------------------------------+  
31259