Overview
The Abstract Factory Pattern is known as a creational pattern. Abstract Factory patterns work around a super-factory which creates other factories.
It provides an interface for creating families of related or dependent objects without specifying their concrete classes.
It has a level of indirection that abstracts the creation of families of related or dependent objects without directly specifying their concrete classes.
The “factory” object has the responsibility for providing creative services for the entire platform family. Clients never create platform objects directly, they ask the factory to do that for them.
This mechanism makes exchanging product families easy because the specific class of the factory object appears only once in the application – where it is instantiated.
The application can wholesale replace the entire family of products simply by instantiating a different concrete instance of the abstract factory.
Let’s understand Problem and Solution with Example
There is a multi-cuisine restaurant. They have only one chef to cook Chinese food.
Now the restaurant owner wants to start Mexican, Italian Foods to be available in his restaurant.
To start this owner needs Mexican food cooked by Mexican Chef, Italian food cooked by Italian Chef but to save costs of all owner wants Chinese chef to cook Mexican and Italian Food.
Abstract Factory pattern provided a way to encapsulate a group of individual factories.
Implementation
We will solve the problem for owners of multi-cuisine restaurant by implementing Abstract Factory Pattern.

Step 1: Abstract Factory Design Pattern Super Classes and Sub Classes
To implement, We need to create basic classes and subclasses for food operations.
0 1 2 3 4 5 6 7 8 9 |
package com.codenuclear.designpattern; public interface ChineseFood { void chineseRice(); void chineseNoodles(); } |
0 1 2 3 4 5 6 7 |
package com.codenuclear.designpattern; public interface MexicanFood { void mexicanNachos(); } |
0 1 2 3 4 5 6 7 |
package com.codenuclear.designpattern; public interface ItalianFood { void italianPasta(); } |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.codenuclear.designpattern; public class ChinesePack implements ChineseFood { @Override public void chineseRice() { System.out.println("Chinese Rice Spicy ordered"); } @Override public void chineseNoodles() { System.out.println("Chinese Noodels with Red Sauce ordered"); } } |
0 1 2 3 4 5 6 7 8 9 10 11 12 |
package com.codenuclear.designpattern; public class MexicanPack implements MexicanFood { @Override public void mexicanNachos() { System.out.println("Mexican Nachos Crispy ordered"); } } |
0 1 2 3 4 5 6 7 8 9 10 11 12 |
package com.codenuclear.designpattern; public class ItalianPack implements ItalianFood { @Override public void italianPasta() { System.out.println("Italian Pasta with White Sauce ordered"); } } |
Step 2: Factory Class for Each subclass
First of all we need to create an Abstract Factory interface or an abstract class.
0 1 2 3 4 5 6 7 8 9 10 11 |
package com.codenuclear.designpattern; public interface Kitchen { public ChineseFood getChineseFood(); public MexicanFood getMexicanFood(); public ItalianFood getItalianFood(); } |
Notice that
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.codenuclear.designpattern; public class ChefA implements Kitchen { @Override public ChineseFood getChineseFood() { System.out.println("Chinese Food Order for ChefA"); return new ChinesePack(); } @Override public MexicanFood getMexicanFood() { System.out.println("Mexican Food Order for ChefA"); return new MexicanPack(); } @Override public ItalianFood getItalianFood() { System.out.println("Italian Food Order for ChefA"); return new ItalianPack(); } } |
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.codenuclear.designpattern; public class ChefB implements Kitchen { @Override public ChineseFood getChineseFood() { System.out.println("Chinese Food Order for ChefB"); return new ChinesePack(); } @Override public MexicanFood getMexicanFood() { System.out.println("Mexican Food Order for ChefB"); return new MexicanPack(); } @Override public ItalianFood getItalianFood() { System.out.println("Italian Food Order for ChefB"); return new ItalianPack(); } } |
Lets write a client test method and see how to use the abstract factory to get the instance of sub-classes.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.codenuclear.designpattern; public class Client { public static void main(String args[]) { Kitchen kitchen = new ChefA(); kitchen.getChineseFood().chineseNoodles(); Kitchen kitchen2 = new ChefB(); kitchen2.getMexicanFood().mexicanNachos(); Kitchen kitchen3 = new ChefA(); kitchen3.getItalianFood().italianPasta(); Kitchen kitchen4 = new ChefB(); kitchen4.getChineseFood().chineseRice(); } } |
Output :
Advantages of Abstract Factory Pattern
It isolates the creation of objects from the client that needs them, giving the client only the possibility of accessing them through an interface, which makes the manipulation easier.
It provides an approach to code for interface rather than implementation.
Abstract Factory pattern is robust and avoid conditional logic of the Factory pattern.
It promotes consistency between products. It is the concrete factory’s job to make sure that the right products are used together.
Drawbacks of Abstract Factory Pattern
Adding a new product requires extending the abstract interface which implies that all of its derived concrete classes also must change.