Chain of responsibility – behavioral design pattern – library MetaTrader 5

//+------------------------------------------------------------------+
//|                                        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 <SRCPatternsPatternOrganizer.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
//+------------------------------------------------------------------+
    📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks