Design patterns – Abstract Factory – library MetaTrader 5

//+----------------+----------------------------------------------------------------------------------------+
//|    Abstract    | Provide an interface for creating families of related or dependent objects without     |
//|     Factory    | specifying their concrete classes.                                                     |
//+----------------+----------------------------------------------------------------------------------------+
//|      When      | 1) a system should be independent of how its products are created, composed, and       |
//|                | represented. 2) a system should be configured with one of multiple families of         |
//|                | products. 3) a family of related product objects is designed to be used together, and  |
//|                | you need to enforce this constraint. 4) you want to provide a class library of         |
//|                | products, and you want to reveal just their interfaces, not their implementations.     |
//+----------------+----------------------------------------------------------------------------------------+
//|                                                Structure                                                |
//+---------------------------------------------------------------------------------------------------------+
//
//               +----------------+                                                              +------+
//               | AbstractFactory|<-------------------------------------------------------------|Client|
//               +----------------+                                                              +------+
//               |CreateProductA()|                                +----------------+                |
//               |CreateProductA()|                                |AbstractProductA|<---------------+
//               +----------------+                                +----------------+                |
//                        ^                                                ^                         |
//                        |                                                |                         |
//            +-----------+-----------+                            +-------+------+                  |
//            |                       |                            |              |                  |
//   +----------------+      +----------------+               +---------+    +---------+             |
//   |ConcreteFactory1|- +   |ConcreteFactory2|- - - - + - - >|ProductA2|    |ProductA1|<- - - +     |
//   +----------------+  |   +----------------+        |      +---------+    +---------+       |     |
//   |CreateProductA()|      |CreateProductA()|                                                      |
//   |CreateProductB()|  |   |CreateProductB()|        |                                       |     |
//   +----------------+      +----------------+                                                      |
//                       |                             |                                       |     |
//                                                                 +----------------+                |
//                       |                             |           |AbstractProductB|<---------|-----+
//                                                                 +----------------+
//                       |                             |                   ^                   |
//                                                                         |
//                       |                             |           +-------+------+            |
//                                                                 |              |
//                       |                             |      +---------+    +---------+       |
//                                                     + - - >|ProductB2|    |ProductB1|<- - - +
//                       |                                    +---------+    +---------+       |
//
//                       |                                                                     |
//                       + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
//
//+-----+----------+----------------------------------------------------------------------------------------+
//| Who | Abstract | declares an interface for operations that create abstract product objects.             |
//|     |  Factory |                                                                                        |
//|     +----------+----------------------------------------------------------------------------------------+
//|     | Concrete | implements the operations to create concrete product objects.                          |
//|     |  Factory |                                                                                        |
//|     +----------+----------------------------------------------------------------------------------------+
//|     | Abstract | declares an interface for a type of product object.                                    |
//|     |  Product |                                                                                        |
//|     +----------+----------------------------------------------------------------------------------------+
//|     | Concrete | 1) defines a product object to be created by the corresponding concrete factory. 2)    |
//|     |  Product | implements the AbstractProduct interface.                                              |
//|     +----------+----------------------------------------------------------------------------------------+
//|     |   Client | uses only interfaces declared by AbstractFactory and AbstractProduct classes.          |
//+-----+----------+----------------------------------------------------------------------------------------+
//|       How      | 1) Normally a single instance of a ConcreteFactory class is created at run-time. This  |
//|                | concrete factory creates product objects having a particular implementation. To        |
//|                | create different product objects, clients should use a different concrete factory. 2)  |
//|                | AbstractFactory defers creation of product objects to its ConcreteFactory subclass.    |
//+----------------+----------------------------------------------------------------------------------------+
//|       Why      | 1) It isolates concrete classes: Clients manipulate instances through their abstract   |
//|                | interfaces. 2) It makes exchanging product families easy: use different product        |
//|                | configurations simply by changing the concrete factory; the whole product family       |
//|                | changes at once. 3) It promotes consistency among products. 4) Supporting new kinds    |
//|                | of products is difficult: requires extending the factory interface, AbstractFactory    |
//|                | class and all of its subclasses.                                                       |
//+----------------+----------------------------------------------------------------------------------------+
//|      Notes     | 1) Factories as singletons. 2) Creating the products: define a factory method for      |
//|                | each product. If many product families are possible, the concrete factory can be a     |
//|                | Prototype: no new concrete factory class for each new product family. 3) Defining      |
//|                | extensible factories: AbstractFactory will only need a single "Make" operation with a  |
//|                | parameter indicating the kind of object to create; all objects have the same abstract  |
//|                | base class.                                                                            |
//+----------------+----------------------------------------------------------------------------------------+
//|                                                   Code                                                  |
//+---------------------------------------------------------------------------------------------------------+
#include <SRCPatternsPatterns.mqh>
namespace AbstractFactory
{
interface AbstractProductA {};
interface AbstractProductB {void Interact(AbstractProductA*);};
interface AbstractFactory
  {
   AbstractProductA* CreateProductA();
   AbstractProductB* CreateProductB();
  };
//--------------------------------------------------------------------
class ProductA1:public AbstractProductA {public:ProductA1(); ~ProductA1();};
void ProductA1::ProductA1(void) {Print(" Product A1 constructed.");}
void ProductA1::~ProductA1(void) {Print(" Product A1 destructed.");}
//--------------------------------------------------------------------
class ProductA2:public AbstractProductA {public:ProductA2(); ~ProductA2();};
void ProductA2::ProductA2(void) {Print(" Product A2 constructed.");}
void ProductA2::~ProductA2(void) {Print(" Product A2 destructed.");}
//--------------------------------------------------------------------
class ProductB1:public AbstractProductB
  {
public:
                     ProductB1();
                    ~ProductB1();
   void              Interact(AbstractProductA*);
  };
void ProductB1::ProductB1(void) {Print(" Product B1 constructed.");}
void ProductB1::~ProductB1(void) {Print(" Product B1 destructed.");}
void ProductB1::Interact(AbstractProductA*p) {Print("  Product B1: ",&this," interacts with Product A: ",p);}
//--------------------------------------------------------------------
class ProductB2:public AbstractProductB
  {
public:
                     ProductB2();
                    ~ProductB2();
   void              Interact(AbstractProductA*);
  };
void ProductB2::ProductB2(void) {Print(" Product B2 constructed.");}
void ProductB2::~ProductB2(void) {Print(" Product B2 destructed.");}
void ProductB2::Interact(AbstractProductA*p) {Print("  Product B2: ",&this," interacts with Product A: ",p);}
//--------------------------------------------------------------------
class Factory1:public AbstractFactory
  {
public:
                     Factory1();
                    ~Factory1();
   AbstractProductA* CreateProductA();
   AbstractProductB* CreateProductB();
  };
//---
void Factory1::Factory1(void) {Print("Factory 1 constructed.");}
void Factory1::~Factory1(void) {Print("Factory 1 destructed.");}
AbstractProductA* Factory1::CreateProductA(void) {return new ProductA1;}
AbstractProductB* Factory1::CreateProductB(void)  {return new ProductB1;}
//--------------------------------------------------------------------
class Factory2:public AbstractFactory
  {
public:
                     Factory2();
                    ~Factory2();
   AbstractProductA* CreateProductA();
   AbstractProductB* CreateProductB();
  };
//---
void Factory2::Factory2(void) {Print("Factory 2 constructed.");}
void Factory2::~Factory2(void) {Print("Factory 2 destructed.");}
AbstractProductA* Factory2::CreateProductA(void) {return new ProductA1;}
AbstractProductB* Factory2::CreateProductB(void) {return new ProductB1;}
//--------------------------------------------------------------------
class FactoryClient
  {
public:
   void              Run();
   void              Switch(AbstractFactory*);
                     FactoryClient(AbstractFactory*);
                    ~FactoryClient();
protected:
   AbstractProductA* apa;
   AbstractProductB* apb;
   AbstractFactory*  factory;
   void              Delete();
  };
//---
void FactoryClient::FactoryClient(AbstractFactory* af)   {Switch(af);}
void FactoryClient::~FactoryClient(void)                 {Delete();}
void FactoryClient::Run(void)                            {apb.Interact(apa);}
void FactoryClient::Delete(void)    {delete apa; delete apb; delete factory;}
void FactoryClient::Switch(AbstractFactory *af)
  {
   Delete();
   factory=af;
   apa=factory.CreateProductA();
   apb=factory.CreateProductB();
  }
//--------------------------------------------------------------------
class Client:public ClientExample {public:string Output(); void Run();};
string Client::Output(void) {return __FUNCTION__;}
void Client::Run()
  {
   FactoryClient client(new Factory1);
   client.Run();
   client.Switch(new Factory2);
   client.Run();
  }
}
//+---------------------------------------------------------------------------------------------------------+
//|                                                  Output                                                 |
//+---------------------------------------------------------------------------------------------------------+
//Creational::AbstractFactory::Client::Output
//Factory 1 constructed.
// Product A1 constructed.
// Product B1 constructed.
//  Product B1: 126877696 interacts with Product A: 125829120
//Factory 2 constructed.
// Product A1 destructed.
// Product B1 destructed.
//Factory 1 destructed.
// Product A2 constructed.
// Product B2 constructed.
//  Product B2: 130023424 interacts with Product A: 128974848
// Product A2 destructed.
// Product B2 destructed.
//Factory 2 destructed.
    📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks