ABSTRACT FACTORY PATTERN

Almost similar to except the fact that it’s more like factory of factories. If you are familiar with factory design pattern in java, you will notice that we have a single Factory class that returns the different sub-classes based on the input provided and factory class uses if-else or switch statement to achieve this. In Abstract Factory pattern, we get rid of if-else block and have a factory class for each sub-class and then an Abstract Factory class that will return the sub-class based on the input factory class.

An abstract factory is a factory that returns factories. Why is this layer of abstraction useful? A normal factory can be used to create sets of related objects. An abstract factory returns factories. Thus, an abstract factory is used to return factories that can be used to create sets of related objects.

As an example, you could have a Honda factory that returns car objects (Brio, Civic, etc.) associated with a Honda factory. You could also have a Hyundai factory that returns car objects (Santro, EON) associated with a Hyundai factory. We could create an abstract factory that returns these different types of car factories depending on the car that we were interested in. We could then obtain car objects from the car factories. Via polymorphism, we can use a common interface to get the different factories, and we could then use a common interface to get the different cars.

Benefits: 

  • Abstract Factory pattern provides approach to code for interface rather than implementation.
  • Abstract Factory pattern is “factory of factories” and can be easily extended to accommodate more products, for example we can add another sub-class Celerio and a factory MarutiFactory.
  • Abstract Factory pattern is robust and avoid conditional logic of Factory pattern.

When to use:

A family of related product objects is designed to be used together, and you need to enforce this constraint.

Example:

ILaptopFactory.java interface

package com.myjavablog.abstractfactory;

public interface ILaptopFactory {

public ILaptopFactory createLaptop(String type);
}

LaptopFactory.java class implementing factory interface –

package com.myjavablog.abstractfactory;

public class LaptopFactory implements ILaptopFactory{

@Override
public ILaptopFactory createLaptop(String type) {

ILaptopFactory laptop = null;

if("Lenovo".equalsIgnoreCase(type))
laptop = new LenovoLaptopFactory();
else if("dell".equalsIgnoreCase(type))
laptop = new DellLaptopFactory();

return laptop;
}
}

 

Then we create different factories for different laptop brands –

LenovoLaptopFactory.java

package com.myjavablog.abstractfactory;

public class LenovoLaptopFactory extends LaptopFactory{

public Lenovo createLenovoLaptop() {
return new Lenovo();
}
}

DellLaptopFactory.java

package com.myjavablog.abstractfactory;

public class DellLaptopFactory extends LaptopFactory{

public Dell createDellLaptop() {
return new Dell();
}
}

Finally TestAbstractFactory.java  to test abstract factory –

package com.myjavablog.abstractfactory;

public class TestAbstractFactory {

public static void main(String[] args) {

System.out.println("Lenovo Configuration");
LaptopFactory factory = new LaptopFactory();
LenovoLaptopFactory llf = (LenovoLaptopFactory) factory.createLaptop("lenovo");
Lenovo len = (Lenovo) llf.createLenovoLaptop();
len.processor();
len.cost();

System.out.println("Dell Configuration");
DellLaptopFactory dlf = (DellLaptopFactory) factory.createLaptop("dell");
Dell dell = (Dell) dlf.createDellLaptop();
dell.processor();
dell.cost();

}
}

 

Usage in JDK:

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()
  • javax.xml.transform.TransformerFactory#newInstance()
  • javax.xml.xpath.XPathFactory#newInstance()
Bitnami