//+----------------+----------------------------------------------------------------------------------------+ //|    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.