Decorator – structural design pattern – library MetaTrader 5

//+------------------------------------------------------------------+
//|                                                    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
//+------------------------------------------------------------------+
📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks