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 | Flyweight - structural design pattern

MetaTrader Experts, Indicators, Scripts and Libraries
//+------------------------------------------------------------------+  //|                                                    Flyweight.mqh |  //|                                    2019-2020, dimitri pecheritsa |  //|                                                 792112@gmail.com |  //+------------------------------------------------------------------+  //| flyweight > structural design pattern                            |  //+------------------------------------------------------------------+  //   design patterns: elements of reusable object-oriented software  //   gof > erich gamma, richard helm, ralph johnson, john vlissides  //   published > 1994  //+------------------------------------------------------------------+  //| intent                                                           |  //+------------------------------------------------------------------+  //   use sharing to support large numbers of fine-grained objects   //    efficiently  //+------------------------------------------------------------------+  //| applicability                                                    |  //+------------------------------------------------------------------+  //   an application uses a large number of objects  //   storage costs are high because of the sheer quantity of objects  //   most object state can be made extrinsic  //   many groups of objects may be replaced by relatively few  //    shared objects once extrinsic state is removed  //   the application doesn't depend on object identity  //      since flyweight objects may be shared, identity tests will  //       return true for conceptually distinct objects  //+------------------------------------------------------------------+  //| structure                                                        |  //+------------------------------------------------------------------+  //  //      |      FlyweightFactory     |o------------------>*|         Flyweight        |  //      |---------------------------|                     |--------------------------|  //   +->|GetFlyweight(key)          |                     |Operation(extrinsic_state)|  //   |  | if(flyweight[key] exists) |                                   ^  //   |  |  return existing flyweight|                                   |  //   |  | else                      |                   +---------------+----------------+  //   |  |  create new flyweight     |                   |                                |  //   |  |  add it to the pool of    |   +->|     ConcreteFlyweight    |   +->|UnsharedConcreteFlyweight |  //   |  |   flyweights              |   |  |--------------------------|   |  |--------------------------|  //   |  |  return the new flyweight |   |  |Operation(extrinsic_state)|   |  |Operation(extrinsic_state)|  //   |                                  |  |--------------------------|   |  |--------------------------|  //   |                                  |  |intrinsic_state           |   |  |all_state                 |  //   |                                  |                                 |  //|Client|------------------------------+---------------------------------+  //  //+------------------------------------------------------------------+  //| diagram — sharing of flyweights                                  |  //+------------------------------------------------------------------+  //  //                                      |aClient|              |aClient|  //                                      |-------|              |-------|  //                                      |   *   |  +-----------|-* *   |  //                                          |      |               |  //                             +------------|------|---------------|--------------+  //                             |flyweights  |      |               |              |  //                             |pool        |      |               |              |  //                             |            v      v               v              |  //|aFlyweightFactory|          |   |ConcreteFlyweight|      |ConcreteFlyweight|   |  //|-----------------|          |   |-----------------|      |-----------------|   |  //|flyweights   *---|----+-----|-->|intrinsic_state  |   +->|intrinsic_state  |   |  //                       |     |                         |                        |  //                       +-----|-------------------------+                        |  //                             +--------------------------------------------------+  //  #include <SRC\Patterns\PatternOrganizer.mqh>  namespace Flyweight  {  //+------------------------------------------------------------------+  //| include — flyweight dictionary — service class                   |  //+------------------------------------------------------------------+  #include "Service\FlyweightDictionary.mqh"  //+------------------------------------------------------------------+  //| participants > flyweight — interface                             |  //+------------------------------------------------------------------+  interface Flyweight  //   declares an interface through which flyweights can receive  //    and act on extrinsic state    {     void Operation(int extrinsic_state);    };  //+------------------------------------------------------------------+  //| participants > concrete flyweight                                |  //+------------------------------------------------------------------+  class ConcreteFlyweight:public Flyweight  //   implements the flyweight interface and adds storage for  //    intrinsic state, if any  //   a concrete flyweight object must be sharable  //   any state it stores must be intrinsic  //      that is, it must be independent of the concrete flyweight  //       object's context    {  public:     void              Operation(int extrinsic_state);  protected:     int               intrinsic_state;    };  //+------------------------------------------------------------------+  //| participants > concrete flyweight > operation                    |  //+------------------------------------------------------------------+  void ConcreteFlyweight::Operation(int extrinsic_state)    {     intrinsic_state=extrinsic_state;     printf("intrinsic state: %d",intrinsic_state);    }  //+------------------------------------------------------------------+  //| participants > unshared concrete flyweight                       |  //+------------------------------------------------------------------+  class UnsharedConcreteFlyweight:public Flyweight  //   not all flyweight subclasses need to be shared  //   the flyweight interface enables concrete sharing — it doesn't enforce it  //   it's common for unshared concrete flyweight objects to have  //    concrete flyweight objects as children at some level  //    in the flyweight object structure    {  protected:     int               all_state;  public:     void              Operation(int extrinsic_state);    };  //+------------------------------------------------------------------+  //| participants > unshared concrete flyweight > operation           |  //+------------------------------------------------------------------+  void UnsharedConcreteFlyweight::Operation(int extrinsic_state)    {     all_state=extrinsic_state;     printf("all state: %d",all_state);    }  //+------------------------------------------------------------------+  //| participants > flyweight factory                                 |  //+------------------------------------------------------------------+  class FlyweightFactory  //   creates and manages flyweight objects  //   ensures that flyweights are shared properly  //      when a client requests a flyweight, the flyweight factory  //       object supplies an existing instance or creates one,  //       if none exists    {  protected:     Dictionary        pool;  public:                       FlyweightFactory(void);     Flyweight*        Flyweight(string key);    };  //+------------------------------------------------------------------+  //| participants > flyweight factory > constructor                   |  //+------------------------------------------------------------------+  FlyweightFactory::FlyweightFactory(void)    {     pool.Add("1",new ConcreteFlyweight);     pool.Add("2",new ConcreteFlyweight);     pool.Add("3",new ConcreteFlyweight);    }  //+------------------------------------------------------------------+  //| participants > flyweight factory > get flyweight                 |  //+------------------------------------------------------------------+  Flyweight* FlyweightFactory::Flyweight(string key)    {     if(!pool.Has(key)) //pool has no such key       {        pool.Add(key,new ConcreteFlyweight()); //create new key—flyweight pair       }     return pool[key]; //return flyweight at key    }  //+------------------------------------------------------------------+  //| participants > client                                            |  //+------------------------------------------------------------------+  class Client:public ClientExample  //   maintains a reference to flyweight(s)  //   computes or stores the extrinsic state of flyweight(s)    {  public:     string            Output();     void              Run();    };  string Client::Output(void)    {     return __FUNCTION__;    }  //+------------------------------------------------------------------+  //| collaborations                                                   |  //+------------------------------------------------------------------+  void Client::Run(void)  //   state that a flyweight needs to function must be characterized  //    as either intrinsic or extrinsic  //      intrinsic state is stored in the concrete flyweight object  //      extrinsic state is stored or computed by client objects  //      clients pass this state to the flyweight when they invoke  //       its operations  //   clients should not instantiate concrete flyweights directly  //      clients must obtain concrete flyweight objects exclusively  //       from the flyweight factory object to ensure they are shared  //       properly    {     int extrinsic_state=7;     Flyweight* flyweight;     FlyweightFactory factory;  //---the extrinsic state is relayed to all flyweights     flyweight=factory.Flyweight("1");     flyweight.Operation(extrinsic_state);     flyweight=factory.Flyweight("10");     flyweight.Operation(extrinsic_state);  //---     flyweight=new UnsharedConcreteFlyweight();     flyweight.Operation(extrinsic_state);     delete flyweight;    }  }  //+------------------------------------------------------------------+  //| output                                                           |  //+------------------------------------------------------------------+  //   Flyweight::Client::Output  //   intrinsic state: 7  //   intrinsic state: 7  //   all state: 7  //+------------------------------------------------------------------+  //| consequences                                                     |  //+------------------------------------------------------------------+  //   flyweights may introduce run-time costs associated with  //    transferring, finding, and/or computing extrinsic state,  //    especially if it was formerly stored as intrinsic state  //   however, such costs are offset by space savings,  //    which increase as more flyweights are shared  //   storage savings  //      are a function of several factors  //         the reduction in the total number of instances  //          that comes from sharing  //         the amount of intrinsic state per object  //         whether extrinsic state is computed or stored  //      the more flyweights are shared, the greater the storage savings  //      the savings increase with the amount of shared state  //      the greatest savings occur when the objects use substantial  //       quantities of both intrinsic and extrinsic state,  //       and the extrinsic state can be computed rather than stored  //       then you save on storage in two ways  //         sharing reduces the cost of intrinsic state,  //         and you trade extrinsic state for computation time  //   the flyweight pattern is often combined with the composite pattern  //    to represent a hierarchical structure as a graph with shared leaf nodes  //      a consequence of sharing is that flyweight leaf nodes  //       cannot store a pointer to their parent  //      rather, the parent pointer is passed to the flyweight  //       as part of its extrinsic state  //      this has a major impact on how the objects in the hierarchy  //       communicate with each other  //+------------------------------------------------------------------+  //| implementation                                                   |  //+------------------------------------------------------------------+  //   removing extrinsic state  //      can be computed from a separate object structure,  //       one with far smaller storage requirements  //   managing shared objects  //      clients shouldn't instantiate them directly  //      clients locate a particular flyweight from associative store  //      also implies some form of reference counting or garbage collection  //+------------------------------------------------------------------+  //| related patterns                                                 |  //+------------------------------------------------------------------+  //   composite  //      hierarchical structure in terms of a  //       directed-acyclic graph with shared leaf nodes  //   state, strategy > as flyweights  //+------------------------------------------------------------------+  
31061