//+------------------------------------------------------------------+ //|                                                    Decorator.mqh | //|                                    2019-2020, dimitri pecheritsa | //|                                                792112@gmail.com | //+------------------------------------------------------------------+ //| decorator < structural design pattern                            | //+------------------------------------------------------------------+ //  design patterns: elements of reusable object-oriented software //  gof > erich gamma, richard helm, ralph johnson, john vlissides //  published in 1994 //+------------------------------------------------------------------+ //| intent                                                          | //+------------------------------------------------------------------+ //  attach — additional responsibilities — to an object dynamically //  provide — flexible alternative to subclassing — for extending //    functionality //+------------------------------------------------------------------+ //| benefits                                                        | //+------------------------------------------------------------------+ //  variable aspect > responsibilities of an object without subclassing //  code refactoring //      inability to alter classes conveniently > also > adapter, visitor //      extending functionality by subclassing //        solution > composition/delegation for combining behavior //        also > bridge, chain of responsibility, composite, //          observer, strategy //+------------------------------------------------------------------+ //| applicability                                                    | //+------------------------------------------------------------------+ //  add responsibilities — to individual objects — //      dynamically and transparently — without affecting other objects //  for responsibilities that can be withdrawn //  when extension by subclassing is impractical //      sometimes a large number of independent extensions are possible //      and would produce an explosion of subclasses to support //      every combination //      or a class definition may be hidden //      or otherwise unavailable for subclassing //+------------------------------------------------------------------+ //| structure                                                        | //+------------------------------------------------------------------+ // //                  | Component |<------------------------------+ //                  |-----------|                              | //                  |Operation()|                              | //                        ^                                    | //                        |                                    | //            +-----------+-------------+                      | //            |                        |            component | //  |ConcreteComponent|    |      Decorator      |-----------+ //  |-----------------|    |-----------------------| //  |Operation()      |    |Operation()            | //                          |  component.Operation()| //                                      ^ //                                      | //                        +-------------+----------+ //                        |                        | //              |ConcreteDecoratorA|  |  ConcreteDecoratorB  | //              |------------------|  |-----------------------| //              |Operation()      |  |Operation()            | //              |------------------|  | Decorator::Operation()| //              |added_state      |  | AddedBehavior()      | //                                    |AddedBehavior()        | // #include <SRCPatternsPatternOrganizer.mqh> namespace Decorator { //+------------------------------------------------------------------+ //| participants > component                                        | //+------------------------------------------------------------------+ class Component //  defines — interface for objects //      can have responsibilities added to them dynamically   { public:   virtual void      Operation(void)=0;   }; //+------------------------------------------------------------------+ //| participants > decorator                                        | //+------------------------------------------------------------------+ class Decorator:public Component //  maintains — reference to a component object //  defines — interface — conforms to component's interface   { public:   Component*        component;   void              Operation(void);   }; //+------------------------------------------------------------------+ //| participants > decorator                                        | //+------------------------------------------------------------------+ void Decorator::Operation(void)   {   if(CheckPointer(component)>0)     {       component.Operation();     }   } //+------------------------------------------------------------------+ //| participants > concrete component                                | //+------------------------------------------------------------------+ class ConcreteComponent:public Component //  defines — object — to which additional responsibilities can be attached   { public:   void              Operation(void);   }; //+------------------------------------------------------------------+ //| participants > concrete component                                | //+------------------------------------------------------------------+ void ConcreteComponent::Operation(void)   {   Print("concrete operation");   } //+------------------------------------------------------------------+ //| participants > concrete decorator                                | //+------------------------------------------------------------------+ //  adds responsibilities to the component //+------------------------------------------------------------------+ //| participants > concrete decorator > a                            | //+------------------------------------------------------------------+ class ConcreteDecoratorA:public Decorator   { protected:   string            added_state; public:                     ConcreteDecoratorA(void);   void              Operation(void);   }; //+------------------------------------------------------------------+ //| participants > concrete decorator > a                            | //+------------------------------------------------------------------+ ConcreteDecoratorA::ConcreteDecoratorA(void):   added_state("added state")   {   } //+------------------------------------------------------------------+ //| participants > concrete decorator > a                            | //+------------------------------------------------------------------+ void ConcreteDecoratorA::Operation(void)   {   Decorator::Operation();   Print(added_state);   } //+------------------------------------------------------------------+ //| participants > concrete decorator > b                            | //+------------------------------------------------------------------+ class ConcreteDecoratorB:public Decorator   { public:   void              AddedBehavior(void);   void              Operation(void);   }; //+------------------------------------------------------------------+ //| participants > concrete decorator > b                            | //+------------------------------------------------------------------+ void ConcreteDecoratorB::AddedBehavior(void)   {   Print("added behavior");   } //+------------------------------------------------------------------+ //| participants > concrete decorator > b                            | //+------------------------------------------------------------------+ void ConcreteDecoratorB::Operation(void)   {   Decorator::Operation();   AddedBehavior();   } //+------------------------------------------------------------------+ //| participants > client                                            | //+------------------------------------------------------------------+ class Client:public ClientExample   { public:   string            Output(void);   void              Run(void);   }; string Client::Output(void) {return __FUNCTION__;} //+------------------------------------------------------------------+ //| collaborations                                                  | //+------------------------------------------------------------------+ void Client::Run(void) //  decorator //      forwards — requests — to its component object //      it may optionally perform — additional operations before and //      after forwarding the request   {   Component* component=new ConcreteComponent();   Decorator* decorator_a=new ConcreteDecoratorA();   Decorator* decorator_b=new ConcreteDecoratorB();   decorator_a.component=component;   decorator_b.component=decorator_a;   decorator_b.Operation(); //---   delete component;   delete decorator_a;   delete decorator_b;   } } //+------------------------------------------------------------------+ //| output                                                          | //+------------------------------------------------------------------+ //  Decorator::Client::Output //  concrete operation //  added state //  added behavior //+------------------------------------------------------------------+ //| consequences                                                    | //+------------------------------------------------------------------+ //  more flexibility than static inheritance //      responsibilities can be added and removed at run-time //      simply by attaching and detaching them //      easy to add a property twice //  avoids feature-laden classes high up in the hierarchy //      add functionality incrementally //        define — new decorators independently //            from the classes of objects they extend //            even for unforeseen extensions //  a decorator and its component aren't identical //  lots of little objects //+------------------------------------------------------------------+ //| implementation                                                  | //+------------------------------------------------------------------+ //  interface conformance > decorator-component //  omitting the abstract decorator class — if single responsibility //  keeping components lightweight //  changing the skin of an object versus changing its guts > strategy //+------------------------------------------------------------------+ //| related patterns                                                | //+------------------------------------------------------------------+ //  adapter > will give an object a completely — new interface //      decorator > changes object's responsibilities, not its interface //  composite //      decorator — is a degenerate composite with only one component — //      not intended for object aggregation //  strategy > change the guts of an object //      decorator > change the skin of an object //+------------------------------------------------------------------+