Abstract factory pattern

Nitin Verma
4 min readApr 20, 2019

Welcome to third pattern in my Design pattern series. Before reading this story make sure that you have read Factory Pattern story.

Prerequisite:

  1. You have read Introduction to design patterns and Factory Pattern.
  2. You understand java or any other OOP language
  3. you have basic idea about inheritance, polymorphism, interfaces
  4. you find my stories interesting 😉

In our Factory Pattern story, we made a pizza shop where regional pizza stores (like NYStylePizzaStore) instantiate that region particular pizza(like NYStyleCheesePizza). Github repository for same can be found here

We can say that each pizza is composed of set of ingredients. A pizza can have following ingredients: Cheese, Sauce, Clams, Dough, Veggies,etc. In New York people like Thin crust and in Chicago people like Thick crust. So if we have a set of ingredients then we can make a new pizza. So now let’s build a factory to create ingredients. Just follow along, it’s not as complicated as it sounds!

Let’s define a interface that all our PizzaIngredient Factories will implement.

public interface PizzaIngredientFactory{
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clam createClam();
}

As previously in factory pattern post, here also we will have different regional factories for ingredients. for eg: below you can see a regional ingredient factory to get a idea of what I am talking about.

public class NYPizzaIngredientFactory implements PizzaIngredientFactory{
public Dough createDough(){
return new ThinCrustDough();
}
public Sauce createSauce(){
return new MarinaraSauce();
}
public Cheese createCheese(){
return new ReggianoCheese();
}
public Veggies[] createVeggies(){
Veggies veggies[] = {new Garlic(), new Onion(), new Mushroom()}
return veggies;
}
public Pepperoni createPepperoni(){
return new SlicedPepperoni();
}
public Clam createClam(){
return new FreshClams();
}
}

Similarly we can have ChicagoPizzaIngredientFactory where we will return Thick crust dough, Mozzarella cheese, frozen clams, plum tomato sauce, sliced pepperoni and some veggies like spinach, black olives.

Note that the new classes that you see here like Dough, Sauce, FreshClams and many more are not available in github repo because that repository is only for Factory Pattern story.

our new Pizza class will look like this. Note that as compared to our previous story Pizza class, we have added some new ingredients and made prepare method as abstract. If you want to compare it with previous story version, click HERE.

As now we have regional pizza stores and regional pizza ingredients, so now we don’t have to make classes for regional pizzas. what it means is that, now we don’t need to have NYStyleCheesePizza /ChicagoStyleVeggiePizza. we simply need to have CheesePizza /VeggiePizza. They will extend our abstract pizza class and implement abstract prepare method.

here’s how one our concrete CheesePizza class will look like

public class CheesePizza extends Pizza{
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory){
this.ingredientFactory = ingredientFactory;
}
void prepare(){
print("preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}

Note that ingredients produced depends on the factory that we are using. eg : In this line of code dough = ingredientFactory.createDough() , Dough type that will be returned depends upon the IngredientFactory that we use. If the factory is of type NYPizzaIngredientFactory then it will return ThinCrustDough.

Region specific pizza stores will use region specific ingredients. eg: NYStylePizzaStorewill use NYPizzaIngredients. so we will couple them together. Here’s how our NYStylePizzaStoreclass will look like now. wanna compare with previous story? click HERE

We have done a lot of changes in our code. Mostly we made new classes. We provided a means of creating a family of ingredients for pizzas by introducing a new type of factory called an Abstract factory.

Abstract factory gives us an interface for creating a family of products without specifying their concrete classes. abstract factories helps us to produce different products for different contexts — such as different regions, different looks, etc.

In the above definition, family of products in our example refer to Dough, Sauce, Cheese, Clams… if we have this family then we can make a pizza.

Let’s try to understand the class diagram. Below I have only shown some part of it (related to New York)

Few important points to be noted here:

  1. The abstract PizzaIngredientFactory is the interface that defines how to make a family of related products.
  2. Clients of the abstract factory are the concrete instances of the pizza abstract class.
  3. Job of the concrete pizza factories is to make pizza ingredients. A factory knows how to create the right object for their region.
  4. Each family produces a different implementation for the family of products. Here we have only shown New York factory, but by now you can easily make Chicago factory also, this factory will create ThickCrustDough instead of ThinCrustDough and similarly for other ingredients.

Below you can see the general class diagram of a abstract factory pattern.

Clap 👏 , Comment and share your valuable feedback and don’t forget to ask more questions in comment section below (if you have any 😉) ✌️

References:
- Head first design patterns book.

--

--

Nitin Verma

Android developer, GIS, writer, Punjabi who love to share knowledge ✌️