/**/
#include <SRC\Patterns\_Main.mqh>
namespace Twin
{
/**************************************************************************************
Design patterns - Twin
Modeling multiple inheritance with the Twin pattern.
/**************************************************************************************
Structure
+-------+ +-------+
|Parent1| |Parent1|
+-------+ +-------+
| M1() | | M2() |
+-------+ +-------+
^ ^
| |
+----|-----------------|----+
| +------+ +------+ |
| |Child1| twin |Child1| |
| +------+ ------> +------+ |
| | M1() | <------ | M1() | |
| | M3() | twin +------+ |
| +------+ |
+---------------------------+
/**************************************************************************************/
class Parent1 {public:void M1() {Print(__FUNCTION__);}};
class Parent2 {public:void M2() {Print(__FUNCTION__);}};
/**************************************************************************************/
class Child1:public Parent1 {public:Parent2*twin;};
/**************************************************************************************/
class Child2:public Parent2
{
public:
Parent1* twin;
void M3() {Print(__FUNCTION__);}
Child2() {child1=new Child1; twin=child1; child1.twin=&this;}
~Child2() {delete child1;}
protected:
Child1* child1;
};
/**************************************************************************************
Applicability
The Twin pattern can be used
*to simulate multiple inheritance in a language that does not support this
feature.
*to avoid certain problems of multiple inheritance such as name clashes.
Participants
Parent1 and Parent2
The classes from which you want to inherit.
Child1 and Child2
The subclasses of Parent1 and Parent2. They are mutually linked via fields.
Each subclass may override methods inherited from its parent. New methods
and fields are usually declared just in one of the subclasses (e.g. in Child1).
Collaborations
Every child class is responsible for the protocol inherited from its parent.
It handles messages from this protocol and forwards other messages to its
partner class.
Clients of the twin pattern reference one of the twin objects directly and
the other via its twin field.
Clients that rely on the protocols of Parent1 or Parent2 communicate with
objects of the respective child class (Child1 or Child2).
Consequences
Although the Twin pattern is able to simulate multiple inheritance, it is not
identical to it. There are several problems that one has to be aware of:
1. Subclassing the Twin pattern. If the twin pattern should again be subclassed,
it is often sufficient to subclass just one of the partners, for example Child1.
In order to pass the interface of both partner classes down to the subclass, it
is convenient to collect the methods of both partners in one class. One can
add the methods of Child2 also to Child1 and let them forward requests to
the other partner.
This solution has the problem that Sub is only compatible with Child1 but
not with Child2. If one wants to make the subclass compatible with both
Child1 and Child2 one has to model it according to the Twin pattern again.
2. More than two parent classes. The Twin pattern can be extended to more
than two parent classes in a straightforward way. For every parent class there
must be a child class. All child classes have to be mutually linked via fields.
Although this is considerably more complex than multiple inheritance, it is
rare that a class inherits from more than two parent classes.
Implementation
The following issues should be considered when implementing the Twin pattern:
1. Data abstraction. The partners of a twin class have to cooperate closely.
They probably have to access each others’ private fields and methods. Most
languages provide features to do that, i.e. to let related classes see more about
each other than foreign classes.
2. Efficiency. The Twin pattern replaces inheritance relationships by composi-
tion. This requires forwarding of messages, which is less efficient than inher-
itance. However, multiple inheritance is anyway slightly less efficient than
single inheritance so that the additional run time costs of the Twin
pattern are not a major problem.
/**************************************************************************************/
class Client:public ClientExample
{
public:
string Output() {return __FUNCTION__;}
void Run()
{
/*child2 inherits the protocols of Parent 1 via twin object and of Parent 2 directly*/
Child2 child2;
/*both twins act as one unit*/
child2.twin.M1();
child2.M2();
child2.M3();
/*Twin pattern is also implemented in the Class Adapter pattern.*/
}
};
}
/**************************************************************************************
Output:
--------------------------------
Structural::Twin::Client::Output
Structural::Twin::Parent1::M1
Structural::Twin::Parent2::M2
Structural::Twin::Child2::M3
/**/
#29787LibrariesMetaTrader 5👁 4873 views
Design patterns - Twin
D
Author
DMITRII PECHERITSAPublished date
Jul 7, 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 →