//+------------------------------------------------------------------+
//| 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 <SRC\Patterns\PatternOrganizer.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
//+------------------------------------------------------------------+
#30969LibrariesMetaTrader 5👁 3879 views
Decorator - structural design pattern
D
Author
DMITRII PECHERITSAPublished date
Sep 9, 2020
📚Related Articles
← View other articles →#77531Libraries
CSetupLedger: a per-setup win rate ledger for Expert Advisors
Why I wrote it My scalper trades two setups. A bullish order block and the bearish mirror of it. The Strategy Tester gave me one profit factor for both of them. I spent two weeks t...
Ali AkbarView detail →
#77488Libraries
Position sizing from risk, using the broker's own tick value and volume step
Every lot size calculator that assumes one pip is worth ten dollars is wrong on gold, wrong on indices, wrong on JPY crosses and wrong on any account not denominated in USD which i...
Ralph Ivan SimeonView detail →
#77156Libraries
PropFirm Defense
A prop firm account runs under a second rulebook MetaTrader 5 knows nothing about: a maximum loss measured from a fixed starting balance, a daily limit that resets at an hour the b...
Bruno Nunes Myrrha RibeiroView detail →