//+------------------------------------------------------------------+ //|                                                      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 //+------------------------------------------------------------------+