Abstract Factory pattern

Abstract Factory design pattern is one of the Creational patterns.

It is very similar to Factory Pattern except that it’s more like factory of factories.

We know that Factory pattern produces different concrete classes based on the input supplied to factory class by implementing if-else conditions within the factory class.

Definition of Abstract Factory

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


In other words,
Abstract Factory pattern allows us to define an interface for creating all distinct products, but leaves the actual product creation to concrete factory classes.

Each factory class corresponds to a certain product variety.


In other words.
Abstract factory pattern will have one interface called “ abstract factory ” which will have several subclasses and each of these subclass is called as“ factory ” and each subclass factory can then be used like factory pattern to produce the set of related objects.

GOFs representation of Abstract factory pattern

AbstractPattern

Let us consider below requirement


We need to read data from different machines like windows and Mac.

Also we need to read different formats of data like pdf,excel etc.

Now we need to use Abstract factory pattern to solve this requirement.

So we will create one abstract factory and 2 sub class factories to represent Mac and windows

Each of these factories Mac and windows produces 2 different set of objects

one to represent PDF data format and other one to represent Excel data format

Let us do this step by step

Step1

Create one abstract class which will be the parent class for all subclasses which factory produces.

  1. package com.kb.abstractfactory;
  2.  
  3. public abstract class FileData {
  4.  
  5.     public abstract void readContent();
  6.    
  7. }
package com.kb.abstractfactory;

public abstract class FileData {

	public abstract void readContent();
	
}


Step2

Create subclasses of the above abstract class to represent Widnows File read operation

In this case, we have 2 sub-classes, one reads data from PDF and other one reads data from Excel

  1. package com.kb.abstractfactory;
  2.  
  3. public class WindowsPDFFileData extends FileData {
  4.    
  5.     @Override
  6.     public void readContent() {
  7.         System.out.println("Read PDF data from Windows Machine");
  8.        
  9.     }
  10.  
  11. }
package com.kb.abstractfactory;

public class WindowsPDFFileData extends FileData {
	
	@Override
	public void readContent() {
		System.out.println("Read PDF data from Windows Machine");
		
	}

}

  1. package com.kb.abstractfactory;
  2.  
  3. public class WindowsExcelFileData extends FileData {
  4.    
  5.     @Override
  6.     public void readContent() {
  7.         System.out.println("Read Excel data from Windows Machine");
  8.        
  9.     }
  10.  
  11. }
package com.kb.abstractfactory;

public class WindowsExcelFileData extends FileData {
	
	@Override
	public void readContent() {
		System.out.println("Read Excel data from Windows Machine");
		
	}

}


Step 3

Create subclasses of the above abstract class to represent Mac File read operation

In this case also, we have 2 subclasses, one reads data from PDF and other one reads data from Excel

  1. package com.kb.abstractfactory;
  2.  
  3. public class MacPDFFileData extends FileData {
  4.    
  5.     @Override
  6.     public void readContent() {
  7.         System.out.println("Read PDF data from Mac Machine");
  8.        
  9.     }
  10.  
  11. }
package com.kb.abstractfactory;

public class MacPDFFileData extends FileData {
	
	@Override
	public void readContent() {
		System.out.println("Read PDF data from Mac Machine");
		
	}

}

  1. package com.kb.abstractfactory;
  2.  
  3. public class MacExcelFileData extends FileData {
  4.  
  5.     @Override
  6.     public void readContent() {
  7.         System.out.println("Read Excel data from Mac Machine");
  8.        
  9.     }
  10.  
  11. }
package com.kb.abstractfactory;

public class MacExcelFileData extends FileData {

	@Override
	public void readContent() {
		System.out.println("Read Excel data from Mac Machine");
		
	}

}


Step 4

Create a main factory interface ReadDataFactory which represents abstract factory

  1. package com.kb.abstractfactory;
  2.  
  3. public interface ReadDataFactory {
  4.    
  5.     public abstract FileData readFileData(String type);
  6.  
  7. }
package com.kb.abstractfactory;

public interface ReadDataFactory {
	
	public abstract FileData readFileData(String type);

}


Step 5

Create sub factories which will in turn create set of objects based on requirement

Subfactory 1 – ReadWindowsDataFactory

  1. package com.kb.abstractfactory;
  2.  
  3. public class ReadWindowsDataFactory implements ReadDataFactory {
  4.  
  5.     @Override
  6.     public FileData readFileData(String type) {
  7.         if(type.equals("pdf")){
  8.             return new WindowsPDFFileData();
  9.  
  10.             }
  11.  
  12.             else if(type.equals("excel")){
  13.             return new WindowsExcelFileData();
  14.  
  15.             }
  16.         return null;
  17.  
  18.     }
  19.  
  20. }
package com.kb.abstractfactory;

public class ReadWindowsDataFactory implements ReadDataFactory {

	@Override
	public FileData readFileData(String type) {
		if(type.equals("pdf")){
			return new WindowsPDFFileData();

			}

			else if(type.equals("excel")){
			return new WindowsExcelFileData();

			}
		return null;

	}

}


Subfactory 2 – ReadMacDataFactory

  1. package com.kb.abstractfactory;
  2.  
  3. public class ReadMacDataFactory implements ReadDataFactory{
  4.  
  5.     @Override
  6.     public FileData readFileData(String type) {
  7.         if(type.equals("pdf")){
  8.             return new MacPDFFileData();
  9.  
  10.             }
  11.  
  12.             else if(type.equals("excel")){
  13.             return new MacExcelFileData();
  14.  
  15.             }
  16.         return null;
  17.  
  18.     }
  19.  
  20. }
package com.kb.abstractfactory;

public class ReadMacDataFactory implements ReadDataFactory{

	@Override
	public FileData readFileData(String type) {
		if(type.equals("pdf")){
			return new MacPDFFileData();

			}

			else if(type.equals("excel")){
			return new MacExcelFileData();

			}
		return null;

	}

}


Step 6

Create a class which uses right object with the help of factory and invokes its method

  1. package com.kb.abstractfactory;
  2.  
  3. public class ReadDataApp {
  4.    
  5.     private FileData fileData;
  6.     public ReadDataApp(ReadDataFactory readDataFactory,String type){
  7.         fileData = readDataFactory. readFileData(type);
  8.     }
  9.     public void readData(){
  10.         fileData.readContent();
  11.     }
  12.  
  13. }
package com.kb.abstractfactory;

public class ReadDataApp {
	
	private FileData fileData;
	public ReadDataApp(ReadDataFactory readDataFactory,String type){
		fileData = readDataFactory. readFileData(type);
	}
	public void readData(){
		fileData.readContent();
	}

}


Step 7

Create a Demo class which acts as a client to use this factory pattern

  1. package com.kb.abstractfactory;
  2.  
  3. public class AbstractFactoryDemo {
  4.  
  5.     public static void main(String[] args) {
  6. //case 1
  7.         ReadDataFactory readWindowsDataFactory = new ReadWindowsDataFactory();
  8.         ReadDataApp readWindowsDataApp = new ReadDataApp(readWindowsDataFactory,"pdf");
  9.         readWindowsDataApp.readData();
  10.  
  11. //case 2
  12.         ReadDataFactory readMacDataFactory = new ReadMacDataFactory();
  13.         ReadDataApp readMacDataApp = new ReadDataApp(readMacDataFactory,"excel");
  14.         readMacDataApp.readData();
  15.  
  16.     }
  17. }
package com.kb.abstractfactory;

public class AbstractFactoryDemo {

	public static void main(String[] args) {
//case 1
		ReadDataFactory readWindowsDataFactory = new ReadWindowsDataFactory();
		ReadDataApp readWindowsDataApp = new ReadDataApp(readWindowsDataFactory,"pdf");
		readWindowsDataApp.readData();

//case 2
		ReadDataFactory readMacDataFactory = new ReadMacDataFactory();
		ReadDataApp readMacDataApp = new ReadDataApp(readMacDataFactory,"excel");
		readMacDataApp.readData();

	}
}


In the above class, we are passing required file format and appropriate sub-factory class and we get the appropriate object gets created from factory and then we have called readData() method of that object

We can see that, in the first case,we have passed format as pdf and sub factory as ReadWindowsDataFactory and in the second case we have passed format as Excel and sub-factory as ReadMacDataFactory

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on