Discussing the article: "Design Patterns in software development and MQL5 (Part 4): Behavioral Patterns 2"

 

Check out the new article: Design Patterns in software development and MQL5 (Part 4): Behavioral Patterns 2.

In this article, we will complete our series about the Design Patterns topic, we mentioned that there are three types of design patterns creational, structural, and behavioral. We will complete the remaining patterns of the behavioral type which can help set the method of interaction between objects in a way that makes our code clean.

Memento

In this section, we are going to identify the Memento pattern as a behavioral design pattern. The Memento pattern can be used to externalize the state of an object to provide rollback functionality, and it is also known as a token.

What does the pattern do?

We can use the Memento pattern when we need to store a snapshot of the state of the object to be restored at a later time, and when a direct interface to get the state would expose the details of the execution and break the encapsulation of the object. So this pattern will capture and externalize the object state to be restored later, the following is a diagram of the structure of this pattern that shows how it can work:

Memento

Author: Mohamed Abdelmaaboud

 

Thank you for this great article. 

I think I implemented the strategy pattern in an Expert Advisor, but maybe in a different way

This could give a more practical example for our beloved readers mind, and for me maybe I would like to get your feedback if I made conceptual mistakes:

I'll simplify the process here:
the Expert itself is an object and becomes the Context:

  • I have an Enum to be able to choose the strategy (as an example STRATEGY_RSI, STRATEGY_MA,...)
  • I have a switch statement in the OnInit(), on the strategy enum, and depending on the result, I  

switch(strategyName)
        {
         case STRATEGY_RSI :
            m_strategy = new Strategy_RSI();
            break;
         case STRATEGY_MA :
            m_strategy = new Strategy_MA();
            break;
         default:
            break;
}

  • I set the input parameters into the strategy through a parameter object (like mqlparams)
[...]
// add the signal parameters to the strategy through the expert Method
Expert.AddParameterObject(signal_RSI_Params); // signal_RSI_Params is the parameter object that has the input parameters inside

//detail of the AddParameterObject method (simplified):
bool CExpert::AddParameterObject(CParameter & parameter)
  {
         if(!m_strategy.AddParameterObject(parameter))
           {
            return(false);
           }
     }
   return true;
  }

// add the generic expert parameters.
Expert.InitStrategyParameters(expert_1_Params);

//detail of the method  (simplified) :
bool CExpert::InitStrategyParameters(CParameter & expertParameters)
  {
// 
   if(!m_strategy.InitStrategyParameters(expertParameters))
     {
     [...]
      return false;
     }
   return true;
  }


  • All the strategies implement the same methods (open a signal, close trade,...)
  • All the strategies can load a Signal or its custom indicators

the in the OnTick function of the expert I call the generic Strategy methods

bool CExpert::CheckOpenLong(void)
  {
    [...]
    if(true == m_strategy.CheckOpenLong([...]))
     {
      [...]
     }
    [...]
}


It's working ver well as I can also test the several strategies / optimisation with the same expert.

The only thing I never found out, besides putting the input parameters in a separate file, is how to load dynamically input parameters according to what the user is choosing as this particularinput parameter (i.e. the strategy input).


I'd like to get your feedback on the way I implemented, is it a strategy pattern, or a hybrid, what could be improved? 

And do you have a idea how we could have (I don't think it's possible with MT5) dynamic contextual input parameters ? 


Thank you so much

Didma 

 

very instructive

 

Why do functions with the same functionality have different names
e.g. here


void Memento::SetState(string state)
  {
   m_state=state;
  }
  
  
void Originator::State(string state)
  {
   m_state=state;
  }




Reason: