Abstract factory pattern in java

Abstract factory pattern is yet another creational design pattern and is considered as another layer of abstraction over factory pattern. In this post, i will expand the problem statement discussed in previous post and will see, how abstract factory pattern solve the problem.

Ads by Google

In my previous post, “Implementing factory design pattern in java“, we discussed how to abstract the car making process for various car model types and their additional logic included in car making process. Lets expand this use case. Now, imagine if our car maker decide to go global.

Becoming global will require to enhance the system to support different car making styles for different countries. For example we will consider USA, Asia and default for all other countries.

Sections in this post:

  • Designing global car factory
  • Implementation in code
  • Final notes

Designing global car factory

In factory pattern implementation, we designed a factory which was suitable for a single location. Supporting multiple locations will need critical design changes.

First of all, we need car factories in each location specified in problem statement. i.e. USACarFactory, AsiaCarFactory and DefaultCarFactory. Now, our application should be smart enough to identify the location where is being used, so we should be able to use appropriate car factory without even knowing which car factory implementation will be used internally. This also saves us from someone calling wrong factory for a particular location.

So basically, we need another layer of abstraction which will identify the location and internally use correct car factory implementation without even giving a single hint to user. This is exactly the problem, which abstract factory pattern is used to solve.

Lets see how abstract factory solve above issue in form of design:

Package Diagram

Abstract fctory design parttern package diagram

Sequence Diagram

abstract factory design pattern sequence diagram

Implementation in code

So, we are ready to write the implementation. Lets hit the keyboard.

Lets write all separate car factories for different locations. Begin with modifying our Car.java class with another attribute: location.

Car.java

public abstract class Car {

	public Car(CarType model, Location location){
		this.model = model;
		this.location = location;
	}

	protected abstract void construct();

	private CarType model = null;
	private Location location = null;

	public CarType getModel() {
		return model;
	}

	public void setModel(CarType model) {
		this.model = model;
	}

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
	}

	@Override
	public String toString() {
		return "Model- "+model + " built in "+location;
	}
}

This adds extra work of creating another enum for storing different locations.

Location.java

public enum Location {
	DEFAULT, USA, ASIA
}

All cat types will also have additional location property. I am writing only for luxury car. Same follows for small and sedan also.

LuxuryCar.java


public class LuxuryCar extends Car
{
	public LuxuryCar(Location location)
	{
		super(CarType.LUXURY, location);
		construct();
	}

	@Override
	protected void construct() {
		System.out.println("Building luxury car");
		//add accessories
	}
}

So for we have created basic classes. Now lets have different car factories.

AsiaCarFactory.java


public class AsiaCarFactory
{
	public static Car buildCar(CarType model)
	{
		Car car = null;
		switch (model)
		{
			case SMALL:
			car = new SmallCar(Location.ASIA);
			break;

			case SEDAN:
			car = new SedanCar(Location.ASIA);
			break;

			case LUXURY:
			car = new LuxuryCar(Location.ASIA);
			break;

			default:
			//throw some exception
			break;
		}
		return car;
	}
}

DefaultCarFactory.java


public class DefaultCarFactory
{
	public static Car buildCar(CarType model)
	{
		Car car = null;
		switch (model)
		{
			case SMALL:
			car = new SmallCar(Location.DEFAULT);
			break;

			case SEDAN:
			car = new SedanCar(Location.DEFAULT);
			break;

			case LUXURY:
			car = new LuxuryCar(Location.DEFAULT);
			break;

			default:
			//throw some exception
			break;
		}
		return car;
	}
}

USACarFactory.java

public class USACarFactory
{
	public static Car buildCar(CarType model)
	{
		Car car = null;
		switch (model)
		{
			case SMALL:
			car = new SmallCar(Location.USA);
			break;

			case SEDAN:
			car = new SedanCar(Location.USA);
			break;

			case LUXURY:
			car = new LuxuryCar(Location.USA);
			break;

			default:
			//throw some exception
			break;
		}
	return car;
	}
}

Well, now we have all 3 different Car factories. Now, we have to abstract the way these factories are accessed. Lets see how?

public class CarFactory
{
	private CarFactory() {
		//Prevent instantiation
	}

	public static Car buildCar(CarType type)
	{
		Car car = null;
		Location location = Location.ASIA; //Read location property somewhere from configuration
		//Use location specific car factory
		switch(location)
		{
			case USA:
			car = USACarFactory.buildCar(type);
			break;
			case ASIA:
			car = AsiaCarFactory.buildCar(type);
			break;
			default:
			car = DefaultCarFactory.buildCar(type);
		}
	return car;
	}
}

We are done with writing code. Now lets test what we have written till now.

public class TestFactoryPattern
{
	public static void main(String[] args)
	{
		System.out.println(CarFactory.buildCar(CarType.SMALL));
		System.out.println(CarFactory.buildCar(CarType.SEDAN));
		System.out.println(CarFactory.buildCar(CarType.LUXURY));
	}
}

Output: (Default location is Asia)

Building small car
Model- SMALL built in ASIA
Building sedan car
Model- SEDAN built in ASIA
Building luxury car
Model- LUXURY built in ASIA

Final notes

We already have seen the use case scenarios of Factory pattern so whenever you need another level of abstraction over a group of factories, you should consider using abstract factory pattern./

You can already look deeper in different implementations of abstract factory in JDK distribution:

There are other similar examples but the need is to have the feel of abstract factory, which you must have got till now.

Happy Learning!!

Ads by Google

9 thoughts on “Abstract factory pattern in java”

  1. Hi Lokesh, Thank you for such nice and simple explanation. I have one question, for example I have two different factories one for fruit, one for Vegetable, question is how can I use abstract factory pattern here.

    1. Talking about myself, I do not see any value addition in making abstract factory for your particular case. Fruits and Vegetables are two different entities and there are many major differences between them. So making two separate factories; one for each, makes more sense to me.

      Also, factory (or abstract factory) pattern should be applied on objects which you can build in different ways; in other words; there can be different representations of a object which belong a common parent.

      Your question is very good but to me, it’s really doesn’t fit into context.

  2. Thanks for the article.Its explained well using the example of car.Now I need a real time scenario where this pattern is used(like factory is used in SessionFactory in hibernate)

Note:- In comment box, please put your code inside [java] ... [/java] OR [xml] ... [/xml] tags otherwise it may not appear as intended.

Leave a Reply

Your email address will not be published. Required fields are marked *


− 2 = three

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>