Design 103 : Why do we need Abstract Factory Pattern now?

Saurabh Kumar
3 min readFeb 5, 2022

We have already seen 2 Factory pattern siblings, why do we need a new one now 🤕!
In the last article, we yet again got stuck at an Issue, since we were using inheritance for providing the object creation capabilities inside PizzaStore, we were not able to inherit from any other base classes or switch the factories at runtime!

public abstract Class PizzaStore {    
Public Pizza OrderPizza(String type)
{
Pizza pizza = createPizza(type);

pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}

Protected abstract Pizza createPizza(String type);
}
// Cannot inherit from some other base class if required.
public Class IndianPizzaStore extends PizzaStore {
@override
Protected Pizza createPizza(String type) {
//..
}
}

What we can do instead is create a Factory Interface itself and store a concrete instance of that Interface inside the PizzaStore to get the required instance we want, i.e use the Abstract Factory Pattern.

What is Abstract Factory Pattern now?
In the Factory Method Pattern we used inheritance to let the subclasses decide which pizza to instantiate but that design came with limitations!
With Abstract Factory Pattern we move that abstract factory method/s out of the creator Class i.e the PizzaStore to an Factory Interface and then use composition to get the required pizza inside our PizzaStore.

Let's understand this with an example from PizzaStore, yet again!

public abstract Class PizzaStore {    
Public Pizza OrderPizza(String type)
{
Pizza pizza = createPizza(type);

pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Protected abstract Pizza createPizza(String type);
}

We don't need this ^^ Abstract PizzaStore anymore, we will compose a factory inside our PizzaStore.

public Class PizzaStore extends WhateverWeWant {    // switch it up at runtime with any factory you want!
private PizzaFactory factory;

public PizzaStore(PizzaFactory factory) {
this.factory = factory;
}
Public Pizza OrderPizza(String type) {
Pizza pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}

Now we can create implementations of the PizzaFactory Interface and use them to generate the required pizza instances inside our PizzaStore with all the goodness composition offers over extension :P

Public Interface PizzaFactory {
Pizza createPizza(String type);
}
Public IndianPizzaFactory implements Pizzafactory { Pizza createPizza(String type) {
//..
}
}

Now we can simply use this IndianPizzaFactory implementation of the PizzaFactory interface for creating pizza instances for us, This is the Abstract Factory Pattern and the problem it specifically solves in a nutshell.

Details to look out for!
1.
Who called it Abstract Factory Pattern and not Factory Interface Pattern
😄?
2. Why didn’t we use the interface instead of the abstract class for the Factory Method pattern itself, why did we create a separate interface and called it Abstract Factory Pattern?
Since we already had fixed implementations for cut(), prepare(), box() and similar methods inside the PizzaStore class so we had to create a new interface.

Thanks for reading this little series of articles on factory patterns!

leave me a clap if you found this article insightful 😄, Happy Reading !

--

--