Abstract Factory Method Design Pattern

Abstract Factory Method Design Pattern


Intent:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes

Mostly used for encapsulating different context. Context can be OS, database, windowing systems.


//The Herbivore class - The 'AbstractProductA' abstract class

class Herbivore

{

public: 

virtual const string& getName(void)=0;

};

//Lets define couple of Herbivores called Cow and Deer

class Cow : public Herbivore //The 'ProductA1' class

{

public: 

Cow():name("Cow"){};//default destructor

const string& getName(void) 

{return name;}

private: 

string name;

};


class Deer : public Herbivore //The 'ProductA2' class

{

public: 

Deer():name("Deer"){}; //default destructor 

const string& getName(void) {return name;}

private: string name;

};


//The Carnivore class - The 'AbstractProductB' abstract class

class Carnivore

{

public: 

virtual const string& getName(void)=0;

virtual void eat(Herbivore& h) = 0;

};


//Lets define couple of Carnivores called Lion and Wolf

class Lion : public Carnivore //The 'ProductB1' class

{

public: 

Lion():name("Lion"){}; 

const string& getName(void) {return name;}

void eat(Herbivore& h) //override 

{   cout << name << " eats " << h.getName() << endl; }

private: 

string name;

};


class Wolf : public Carnivore //The 'ProductB2' class

{

public: 

Wolf():name("Wolf"){}; 

const string& getName(void) {return name;} 

void eat(Herbivore& h) //override  

{   cout << name << " eats " << h.getName() << endl; }

private:

string name;

};


//The 'AbstractFactory' abstract class

class ContinentFactory

{

public: 

virtual Herbivore& CreateHerbivore() = 0; 

virtual Carnivore& CreateCarnivore() = 0;

};


class AfricaFactory : public ContinentFactory//The 'ConcreteFactory1' class

{ 

Herbivore& CreateHerbivore() 

{   

return *(dynamic_cast<Herbivore *>(new Cow())); 

} 

Carnivore& CreateCarnivore() 

{   

return *(dynamic_cast<Carnivore *>(new Lion())); 

}

};


class AmericaFactory : public ContinentFactory //The 'ConcreteFactory2' class

{ 

Herbivore& CreateHerbivore() 

{   

return *(dynamic_cast<Herbivore *>(new Deer())); 

} 

Carnivore& CreateCarnivore() 

{  

return *(dynamic_cast<Carnivore *>(new Wolf()));

}

};


//The 'Client' class

class AnimalWorld

{

public: 

AnimalWorld(ContinentFactory& factory):_herbivore(factory.CreateHerbivore()),

_carnivore(factory.CreateCarnivore()) 

{ } 

void RunFoodChain() 

{  

_carnivore.eat(_herbivore); 

}

private: 

Herbivore& _herbivore;

Carnivore& _carnivore;

};


int main()

{ 

//Create and run African Animal World 

ContinentFactory& africa = *(dynamic_cast<ContinentFactory *>(new AfricaFactory()));

AnimalWorld& world1 = *(new AnimalWorld(africa)); 

world1.RunFoodChain(); 

// Create and run the American animal world

ContinentFactory& america = *(dynamic_cast<ContinentFactory *>(new AmericaFactory()));

AnimalWorld& world2 = *(new AnimalWorld(america)); 

world2.RunFoodChain(); 

return 0;

}


Consequences:


Advantages:

By changing only the factory, the whole family of objects change. It promotes consistency among products because an application can use objects only from one family at a time.


Disadvantages:

New products cannot be supported easily because the AbstractFactory intereface fixes the set of products that can be created. If a new product is to be supported, it would involve changing the AbstractFactory and all its sub classes.


When to use this pattern:

Use abstract factory 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 system should be able to use classes only from one family at a time and you want to enforce that.



Difference between Factory Method and Abstract Factory Method:

Factory Method

Abstract Factory

Manages the creation of object without depending on its concrete type.

Manages creation of related families or interdependent classes without depending on their concrete types.

Sub classes manage the creation of the concrete type

Creation depends on the type of factory used.

Easy to extend the factory class to support new products.

Difficult to extend the factories to support new products.

Many factories can be used simultaneously.

Only once factory is used at a time.



Setup VSCode with Salesforce

Step by Step guide to setup VSCode with Salesforce Install vscode Install Salesforce CLI (developer.salesforce.com/tools/sfdxcli) Perform fo...