An Abstract Factory is the extension of the Factory method pattern and provides an abstraction one level higher than the factory method pattern.

In short the Abstract Factory creates an object of some other factories which at the end creates an object of concrete classes. Or we can say the Abstract Factory encapsulates individual factories having a single theme.

Like a Factory method it falls under the creational pattern.

According to the Gang of Four: It provides an Interface for creating families of related or dependent objects without specifying their concrete classes.

Let's consider the same example we used for the Factory method pattern.There we had a class called CustomerFactory which creates various customers according to input it gets.

Now the Company decides to extend the application and they say, all customers belonging to a specified country (country 1) and who are of Grade1 get a 200 Rs discount and Grade2 customers belonging to another country (country 2) get a discount of 100Rs, and remaining ____.

So the CustomerFactory ends up with a code which looks like this:

publicIBaseCustomer GetCustomer(string CustomerType, string Country)

{

switch(CustomerType)

{

case"1":

switch(Country)

{

case"Country1":

{

IBaseCustomer c = newGrade1Customer();

c.DiscountAmount = 200;

return c;

}

default:

{

IBaseCustomer c = newGrade1Customer();

c.DiscountAmount = 0;

return c;

}

}

case"2":

switch(Country)

{

case "Country2":

{

IBaseCustomer c = newGrade2Customer();

c.DiscountAmount = 100;

return c;

}

default:

{

IBaseCustomer c = newGrade1Customer();

c.DiscountAmount = 0;

return c;

}

}

default:

{

IBaseCustomer c = newGrade1Customer();

c.DiscountAmount = 0;

return c;

}

}

}

.

.

.

.

Client Code

CustomerFactory factory=new CustomerFactory();

IBaseCustomer c= factory. GetCustomer("1","Country1");

c.getAmount()//display;

Problem

Factory ends up with too many case (or if) conditions, and every new country results in two or more case conditions.

One solution is to create 3 different factories, Country1Factory, Country2Factory and OtherFactory. Which means every new country results in recompilation of client code, also the client needs to be aware of each and every factory.

Abstract Factory Pattern as the solution

Here a higher level factory is created which will act as a factory for other factories and those factories will create the final concrete classes as per specifications.

The Components involved in the Abstarct Factory Method Pattern are:

Product: IBaseCustomer

Concrete Product: Grade1Customer and Grade2Customer

BaseFactory: CustomerFactory

Concrete Factory: Country1Factory and Country2Factory

Let's modify the previous code.

Output

Step 1

Create a Base Factory or we can ____ Factory of Factories called CustomerFactory; see:

publicclassCustomerFactory{}

Step 2

Create a static method which will create more factories as per requirements; see:

publicstaticCustomerFactory GetCustomerFactory(string Country)

{

switch(Country)

{

case"Country1":

{

returnnewCountry1Factory();

}

case"Country2":

{

returnnewCountry2Factory();

}

default:

{

returnnewCustomerFactory();//Returning itself for Default

}

}

}

Step 3

Add a virtual method inside the CustomerFactory for creating final concrete classes; see:

publicvirtualIBaseCustomer GetCustomer(string CustomerType)

{

switch(CustomerType)

{

case"1":

Grade1Customer c1 = newGrade1Customer();

c1.DiscountAmount = 0;

return c1;

case"2":

Grade2Customer c2 = newGrade2Customer();

c2.DiscountAmount = 0;

return c2;

default:

returnnull;

}

}

Step 4

Define concrete factories, and inherit them from base factories i.e, from CustomerFactory; see:

CustomerFactory

publicclassCountry1Factory : CustomerFactory

{

}

publicclassCountry2Factory : CustomerFactory

{

}

Step 5

Override virtual methods in concrete factories according to requirements and return final concrete classes; see: