Facade – structural design pattern – library MetaTrader 5

//+------------------------------------------------------------------+
//|                                                       Facade.mqh |
//|                                    2019-2020, dimitri pecheritsa |
//|                                                 792112@gmail.com |
//+------------------------------------------------------------------+
//| facade > structural design pattern                               |
//+------------------------------------------------------------------+
//   design patterns: elements of reusable object-oriented software
//   gof > erich gamma, richard helm, ralph johnson, john vlissides
//   published > 1994
//+------------------------------------------------------------------+
//| intent                                                           |
//+------------------------------------------------------------------+
//   provide a unified interface to a set of interfaces in a subsystem
//   facade defines a higher-level interface that makes the subsystem
//    easier to use
//+------------------------------------------------------------------+
//| applicability                                                    |
//+------------------------------------------------------------------+
//   you want to provide a simple interface to a complex subsystem
//      subsystems often get more complex as they evolve
//      most patterns, when applied, result in more and smaller classes
//      this makes the subsystem more reusable and easier to customize, 
//       but it also becomes harder to use for clients that don't need to
//       customize it
//      a facade can provide a simple default view of the subsystem 
//       that is good enough for most clients
//      only clients needing more customizability will need to look 
//       beyond the facade
//   there are many dependencies between clients and the implementation 
//    classes of an abstraction
//      introduce a facade to decouple the subsystem from clients and
//       other subsystems, thereby promoting subsystem independence 
//       and portability
//   you want to layer your subsystems
//      use a facade to define an entry point to each subsystem level
//      if subsystems are dependent, then you can simplify the
//       dependencies between them by making them communicate 
//       with each other solely through their facades
//+------------------------------------------------------------------+
//| structure                                                        |
//+------------------------------------------------------------------+
//
//   +---------------------------|facade|-------------------------+
//   |  subsystem classes            |                            |
//   |                               |                            |
//   |  -------       -------        |            --------        |
//   | |       |--+  |       |<------+           |        |       |
//   |  -------   |   -------        |            --------        |
//   |     ^      |                  |               ^            |
//   |     |      |      -------     |               |            |
//   |     |      +-----|       |<---+         +-----+-----+      |
//   |     |             -------     |         |           |      |
//   |  -------                      |     --------    --------   |
//   | |       |<--------------------+--->|        |  |        |  |
//   |  -------                            --------    --------   |
//   |                                                            |
//   +------------------------------------------------------------+
//
#include <SRCPatternsPatternOrganizer.mqh>
namespace Facade
{
//+------------------------------------------------------------------+
//| participants > subsystem classes                                 |
//+------------------------------------------------------------------+
//   implement subsystem functionality
//   handle work assigned by the facade object
//   have no knowledge of the facade — keep no references to it
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem a                   |
//+------------------------------------------------------------------+
class SubSystemA
  {
public:
   void              Operation(void);
  };
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem a > opereation      |
//+------------------------------------------------------------------+
void SubSystemA::Operation(void)
  {
   Print("subsystem a > operation");
  }
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem b                   |
//+------------------------------------------------------------------+
class SubSystemB
  {
public:
   void              Operation(void);
  };
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem b > opereation      |
//+------------------------------------------------------------------+
void SubSystemB::Operation(void)
  {
   Print("subsystem b > operation");
  }
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem c                   |
//+------------------------------------------------------------------+
class SubSystemC
  {
public:
   void              Operation(void);
  };
//+------------------------------------------------------------------+
//| participants > subsystem classes > subsystem c > opereation      |
//+------------------------------------------------------------------+
void SubSystemC::Operation(void)
  {
   Print("subsystem c > operation");
  }
//+------------------------------------------------------------------+
//| participants > facade                                            |
//+------------------------------------------------------------------+
class Facade
//   knows which subsystem classes are responsible for a request
//   delegates client requests to appropriate subsystem objects
  {
public:
   void              OperationAB(void);
   void              OperationBC(void);
protected:
   SubSystemA        subsystem_a;
   SubSystemB        subsystem_b;
   SubSystemC        subsystem_c;
  };
//+------------------------------------------------------------------+
//| participants > facade > operation a—b                            |
//+------------------------------------------------------------------+
void Facade::OperationAB(void)
  {
   Print("facade > operation a & b");
   Print("facade > requesting > subsystem a > operation");
   subsystem_a.Operation();
   Print("facade > requesting > subsystem b > operation");
   subsystem_b.Operation();
  }
//+------------------------------------------------------------------+
//| participants > facade > operation b—c                            |
//+------------------------------------------------------------------+
void Facade::OperationBC(void)
  {
   Print("facade > operation b & c");
   Print("facade > requesting > subsystem b > operation");
   subsystem_b.Operation();
   Print("facade > requesting > subsystem c > operation");
   subsystem_c.Operation();
  }
//+------------------------------------------------------------------+
//| participants > client                                            |
//+------------------------------------------------------------------+
class Client:public ClientExample
  {
public:
   string            Output(void);
   void              Run(void);
  };
string Client::Output(void)
  {
   return __FUNCTION__;
  }
//+------------------------------------------------------------------+
//| collaborations                                                   |
//+------------------------------------------------------------------+
void Client::Run(void)
//   clients communicate with the subsystem by sending requests to facade
//    which forwards them to the appropriate subsystem object(s)
//      although the subsystem objects perform the actual work,
//       the facade may have to do work of its own to translate its
//       interface to subsystem interfaces
//   clients that use the facade don't have to access its subsystem
//    objects directly
  {
   Facade facade;
   Print("client > requesting > facade operation a & b");
   facade.OperationAB();
   Print("client > requesting > facade operation b & c");
   facade.OperationBC();
  }
}
//+------------------------------------------------------------------+
//| output                                                           |
//+------------------------------------------------------------------+
//   Facade::Client::Output
//   client > requesting > facade operation a & b
//   facade > operation a & b
//   facade > requesting > subsystem a > operation
//   subsystem a > operation
//   facade > requesting > subsystem b > operation
//   subsystem b > operation
//   client > requesting > facade operation b & c
//   facade > operation b & c
//   facade > requesting > subsystem b > operation
//   subsystem b > operation
//   facade > requesting > subsystem c > operation
//   subsystem c > operation
//+------------------------------------------------------------------+
//| consequences                                                     |
//+------------------------------------------------------------------+
//   it shields clients from subsystem components,
//    thereby reducing the number of objects that clients deal with
//    and making the subsystem easier to use
//   it promotes weak coupling between the subsystem and its clients
//      often the components in a subsystem are strongly coupled
//      weak coupling lets you vary the components of the subsystem
//       without affecting its clients
//      facades help layer a system and the dependencies between objects
//      they can eliminate complex or circular dependencies
//      this can be an important consequence when the client
//       and the subsystem are implemented independently
//      reducing compilation dependencies is vital in large software systems
//      you want to save time by minimizing recompilation when
//       subsystem classes change
//      reducing compilation dependencies with facades can limit the
//       recompilation needed for a small change in an important subsystem
//      a facade can also simplify porting systems to other platforms,
//       because it's less likely that building one subsystem requires
//       building all others
//   it doesn't prevent applications from using subsystem classes
//    if they need to
//      thus you can choose between ease of use and generality
//+------------------------------------------------------------------+
//| implementation                                                   |
//+------------------------------------------------------------------+
//   reducing client-subsystem coupling
//      the coupling between clients and the subsystem can be reduced
//       even further by making facade an abstract class with
//       concrete subclasses for different implementations of a subsystem
//      then clients can communicate with the subsystem through the
//       interface of the abstract facade class
//      this abstract coupling keeps clients from knowing which
//       implementation of a subsystem is used
//      an alternative to subclassing is to configure a facade object
//       with different subsystem objects
//      to customize the facade, simply replace one or more of its
//       subsystem objects
//   public versus private subsystem classes
//      a subsystem is analogous to a class in that both have interfaces,
//       and both encapsulate something—a class encapsulates state
//       and operations, while a subsystem encapsulates classes
//      and just as it's useful to think of the public and private
//       interface of a class, we can think of the public and private
//       interface of a subsystem
//      the public interface to a subsystem consists of classes that
//       all clients can access
//      the private interface is just for subsystem extenders
//      the facade class is part of the public interface, of course,
//       but it's not the only part
//      other subsystem classes are usually public as well
//+------------------------------------------------------------------+
//| related patterns                                                 |
//+------------------------------------------------------------------+
//   abstract factory
//      can be used with facade to provide an interface for creating
//       subsystem objects in a subsystem-independent way
//      abstract factory can also be used as an alternative to facade
//       to hide platform-specific classes
//   mediator
//      is similar to facade in that it abstracts functionality of
//       existing classes
//      however, mediator's purpose is to abstract arbitrary
//       communication between colleague objects, often centralizing
//       functionality that doesn't belong in any one of them
//      mediator's colleagues are aware of and communicate with the
//       mediator instead of communicating with each other directly
//      in contrast, a facade merely abstracts the interface to
//       subsystem objects to make them easier to use
//         it doesn't define new functionality, and subsystem
//          classes don't know about it
//   singleton
//      usually only one facade object is required
//       thus facade objects are often singletons
//+------------------------------------------------------------------+
    📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks