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

MetaTrader Experts, Indicators, Scripts and Libraries
//+------------------------------------------------------------------+  //|                                                    Composite.mqh |  //|                                    2019-2020, dimitri pecheritsa |  //|                                                 792112@gmail.com |  //+------------------------------------------------------------------+  //| src > patterns > structural > composite                          |  //+------------------------------------------------------------------+  //   design patterns: elements of reusable object-oriented software  //   gof > erich gamma, richard helm, ralph johnson, john vlissides  //   published in 1994  //+------------------------------------------------------------------+  //| intent                                                           |  //+------------------------------------------------------------------+  //   object tree > represents > part-whole hierarchies  //   client > treats uniformly > objects and compositions of objects  //+------------------------------------------------------------------+  //| benefits                                                         |  //+------------------------------------------------------------------+  //   variable aspect > structure and composition of an object  //   refactoring > problem > extending functionality < by subclassing   //   refactoring > solution > composition/delegation > combine behavior  //      also > bridge, chain of responsibility, composite, decorator,  //       observer, strategy  //+------------------------------------------------------------------+  //| applicability                                                    |  //+------------------------------------------------------------------+  //   represent > part-whole hierarchies of objects  //   clients > ignore > difference  //      compositions of objects and individual objects  //   clients > treat uniformly > composite structure objects  //+------------------------------------------------------------------+  //| structure                                                        |  //+------------------------------------------------------------------+  //  //     |Client|----->|    Component    |*<------------------+  //                   |-----------------|                    |  //                   |Operation()      |                    |   //                   |Add(Component)   |                    |  //                   |Remove(Component)|                    |  //                   |GetChild(int)    |                    |  //                            ^                             |  //                            |                             |  //                    +-------+-----------+                 |  //                    |                   |           nodes |  //              |   Leaf    |   |     Composite     |o------+  //              |-----------|   |-------------------|  //              |Operation()|   |Operation()        |  //                              | for all n in nodes|  //                              |  n.Operation()    |  //                              |Add(Component)     |  //                              |Remove(Component)  |  //                              |GetChild(int)      |  //  //+------------------------------------------------------------------+  //| typical object structure                                         |  //+------------------------------------------------------------------+  //  //                        +---->|aLeaf|  //                        |  //       |aComposite|-----+---->|aLeaf|         +---->|aLeaf|  //                        |                     |  //                        +---->|aComposite|----+---->|aLeaf|  //                        |                     |  //                        +---->|aLeaf|         +---->|aLeaf|  //  #include <SRC\Patterns\PatternOrganizer.mqh>  namespace Composite  {  //+------------------------------------------------------------------+  //| participants                                                     |  //+------------------------------------------------------------------+  class Component  //   declares > interface   //      objects < composition  //      accessing and managing child components  //   default behavior > interface > common to all classes  //   optional > interface  //      accessing > component's parent in the recursive structure  //      implements it if that's appropriate    {  public:     virtual void      Operation(void)=0;     virtual void      Add(Component*)=0;     virtual void      Remove(Component*)=0;     virtual Component*   GetChild(int)=0;                       Component(void);                       Component(string);  protected:     string            name;    };  Component::Component(void) {}  Component::Component(string a_name):name(a_name) {}  //+------------------------------------------------------------------+  //| participants                                                     |  //+------------------------------------------------------------------+  #define ERR_INVALID_OPERATION_EXCEPTION   1  //user error for adding/removing a component to a leaf  class Leaf:public Component  //   represents > leaf objects < composition  //   no children  //   defines > behavior > primitive objects in the composition    {  public:     void              Operation(void);     void              Add(Component*);     void              Remove(Component*);     Component*        GetChild(int);                       Leaf(string);    };  void Leaf::Leaf(string a_name):Component(a_name) {}  void Leaf::Operation(void) {Print(name);}  void Leaf::Add(Component*) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION);}  void Leaf::Remove(Component*) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION);}  Component* Leaf::GetChild(int) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION); return NULL;}  //+------------------------------------------------------------------+  //| participants                                                     |  //+------------------------------------------------------------------+  class Composite:public Component  //   defines > behavior for components having children  //   stores > child components  //   implements > child-related operations > in component interface    {  public:     void              Operation(void);     void              Add(Component*);     void              Remove(Component*);     Component*        GetChild(int);                       Composite(string);                      ~Composite(void);  protected:     Component*        nodes[];    };  Composite::Composite(string a_name):Component(a_name) {}  //+------------------------------------------------------------------+  //| participants > composite                                         |  //+------------------------------------------------------------------+  Composite::~Composite(void)    {     int total=ArraySize(nodes);     for(int i=0; i<total; i++)       {        Component* i_node=nodes[i];        if(CheckPointer(i_node)==1)          {           delete i_node;          }       }    }  //+------------------------------------------------------------------+  //| participants > composite                                         |  //+------------------------------------------------------------------+  void Composite::Operation(void)    {     Print(name);     int total=ArraySize(nodes);     for(int i=0; i<total; i++)       {        nodes[i].Operation();       }    }  //+------------------------------------------------------------------+  //| participants > composite                                         |  //+------------------------------------------------------------------+  void Composite::Add(Component *src)    {     int size=ArraySize(nodes);     ArrayResize(nodes,size+1);     nodes[size]=src;    }  //+------------------------------------------------------------------+  //| participants > composite                                         |  //+------------------------------------------------------------------+  void Composite::Remove(Component *src)    {     int find=-1;     int total=ArraySize(nodes);     for(int i=0; i<total; i++)       {        if(nodes[i]==src)          {           find=i;           break;          }       }     if(find>-1)       {        ArrayRemove(nodes,find,1);       }    }  //+------------------------------------------------------------------+  //| participants > composite                                         |  //+------------------------------------------------------------------+  Component* Composite::GetChild(int i)    {     return nodes[i];    }  //+------------------------------------------------------------------+  //| participants                                                     |  //+------------------------------------------------------------------+  class Client:public ClientExample  //   manipulates objects in the composition through the component interface    {  public:     string            Output(void);     void              Run(void);    };  string Client::Output(void) {return __FUNCTION__;}  //+------------------------------------------------------------------+  //| collaborations                                                   |  //+------------------------------------------------------------------+  void Client::Run(void)  //   clients use the component class interface  //      to interact with objects in the composite structure  //   if the recipient is a leaf > the request is handled directly  //   if the recipient is a composite  //      it usually forwards requests to its child components  //      possibly performing additional operations  //       before and/or after forwarding    {     Component* root=new Composite("root"); //make root  //---make components     Component* branch1=new Composite(" branch 1");     Component* branch2=new Composite(" branch 2");     Component* leaf1=new Leaf("  leaf 1");     Component* leaf2=new Leaf("  leaf 2");  //---build tree     root.Add(branch1);     root.Add(branch2);     branch1.Add(leaf1);     branch1.Add(leaf2);     branch2.Add(leaf2);     branch2.Add(new Leaf("  leaf 3"));  //---check     printf("tree:");     root.Operation();  //---change tree     root.Remove(branch1); //remove whole branch  //---check     printf("tree after removal of one branch:");     root.Operation();  //---finish     delete root;     delete branch1;    }  }  //+------------------------------------------------------------------+  //| output                                                           |  //+------------------------------------------------------------------+  //   Structural::Composite::Client::Output  //   tree:  //   root  //    branch 1  //     leaf 1  //     leaf 2  //    branch 2  //     leaf 2  //     leaf 3  //   tree after removal of one branch:  //   root  //    branch 2  //     leaf 2  //     leaf 3  //+------------------------------------------------------------------+  //| consequences                                                     |  //+------------------------------------------------------------------+  //   defines class hierarchies consisting of primitive objects and composite objects  //   makes the client simple  //   makes it easier to add new kinds of components  //   can make your design overly general  //+------------------------------------------------------------------+  //| implementation                                                   |  //+------------------------------------------------------------------+  //   explicit parent references (in component)  //      simplify the traversal and management of a composite structure  //      help support the chain of responsibility pattern  //   sharing components  //      flyweight can rework a design to avoid storing parents altogether  //   maximizing the component interface  //      default implementations, leaf and composite will override them  //   declaring the child management operations  //      at the root of the class hierarchy > transparency  //      in the composite > afety  //      usually it's better to make add and remove fail by default  //         if the component isn't allowed to have children  //         or if the argument of remove isn't a child of the component  //   component may implement a list of components  //      if there are relatively few children in the structure  //   child ordering > design child access/management carefully > iterator  //   caching to improve performance  //      when components know their parents  //      tell composites that their caches are invalid  //   composite is responsible for deleting its children  //      when it's destroyed, unless leafs can be shared  //   composites store children in  //      linked lists, trees, arrays, and hash tables  //+------------------------------------------------------------------+  //| related patterns                                                 |  //+------------------------------------------------------------------+  //   chain of responsibility > component-parent link  //   decorator > common parent class > for decorators and composites  //   flyweight > share components (no longer refer to their parents)  //   iterator > traverse composites  //   visitor > localizes operations and behavior  //      distributed across composite and leaf classes  //+------------------------------------------------------------------+  
30884