Abstract Factory Pattern

Abstract Factory pattern works around a super-factory which creates other factories. This factory is also called as a factory of factories. Abstract Factory design pattern comes under Creational Design Pattern as this pattern provides one of the best ways to create Objects.

In Abstract Factory pattern an interface is responsible for creating a factory of related objects without explicitly specifying their classes. Each generated factory can give the objects as per the Factory pattern.The definition of Abstract Factory provided in the original Gang of Four book on Design Patterns states: 

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

Now, let's take a look at the diagram definition of the Abstract Factory Pattern.

 

 

The AbstractFactory defines the interface that all of the concrete factories will need to implement in order to create a ProductConcreteFactoryOne and ConcreteFactoryTwo have both implemented this interface here, creating two separate families of product. Meanwhile, AbstractProductOne and AbstractProductTwo are interfaces for the different types of product. Each factory will create one of each of these Abstract Product. 

The Client deals with AbstractFactoryAbstractProductOne and AbstractProductTwo. It doesn't know anything about the implementations. The actual implementation of AbstractFactory that the Client uses is determined at runtime.

As you can see, one of the main benefits of this pattern is that the client is totally decoupled from the concrete products. Also, new product families can be easily added into the system, by just adding in a new type of ConcreteFactory that implements AbstractFactory, and creating the specific Product implementations.

Implementation

We are going to create a TwoWheeler and FourWheeler interfaces and concrete classes implementing these interfaces. We create an abstract factory class AbstractVehicleFactory as next step. Concrete Factory classes like FourWheelerFactory and TwoWheelerFactory extends AbstractVehicleFactory. A factory creator/generator class FactoryProducer is created.

AbstractFactoryPatternDemo, our demo class uses FactoryProducer to get a AbstractVehicleFactory object by passing FourWheeler/TwoWheeler to it. Once it get the correct factory, then it will pass the Model and Color information of the required vehicle to get an instance of it. Here we are using a supporting class with some enums to define the Model and Color of a vehicle.

package com.tuturself.abstractfactory;

public class Configuration {

	public enum Model {
		Bmw, Mercedes, Pulsar, Apache, Duke, Audi;
	}

	public enum Color {
		Red, Blue, Silver, Purple;
	}
}

 Let us have a look in the class diagram of the example implementation.

 

 

 

Step 1

Create an abstract class for FourWheeler.

package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public abstract class FourWheeler {

	public int registrationNo;
	public Model model;
	public Color color;

	public FourWheeler(int registrationNo) {
		this.registrationNo = registrationNo;
		setModel();
	}

	public abstract void setModel();

	public abstract void setColor(Color color);

	public void display() {
		System.out.println("--------- FourWheeler ---------");
		System.out.println("Registration No: " + registrationNo);
		System.out.println("Model: " + model);
		System.out.println("Color: " + color);
	}
}

 

Step 2

Create concrete Car classes implementing the above abstract class.

# BMW.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class BMW extends FourWheeler {

	public BMW(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Bmw;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

# Audi.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class Audi extends FourWheeler {

	public Audi(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Audi;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

# Mercedes.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class Mercedes extends FourWheeler {

	public Mercedes(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Mercedes;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

 

Step 3

Create an abstract class for TwoWheeler.

package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public abstract class TwoWheeler {
	public int registrationNo;
	public Model model;
	public Color color;

	public TwoWheeler(int registrationNo) {
		this.registrationNo = registrationNo;
		setModel();
	}

	public abstract void setModel();

	public abstract void setColor(Color color);

	public void display() {
		System.out.println("--------- TwoWheeler ---------");
		System.out.println("Registration No: " + registrationNo);
		System.out.println("Model: " + model);
		System.out.println("Color: " + color);
	}
}

 

Step 4

Create concrete Bike classes implementing the above abstract class.

# Apache.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class Apache extends TwoWheeler {

	public Apache(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Apache;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

# Pulsar.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class Pulsar extends TwoWheeler {

	public Pulsar(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Pulsar;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

# Duke.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class Duke extends TwoWheeler {

	public Duke(int registrationNo) {
		super(registrationNo);
	}

	@Override
	public void setModel() {
		this.model = Model.Pulsar;
	}

	@Override
	public void setColor(Color color) {
		this.color = color;
	}
}

 

Step 5

Create an Abstract class to get factories for TwoWheeler and FourWheeler Objects. Which is the AbstractFactory class.

AbstractVehicleFactory.java

package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public abstract class AbstractVehicleFactory {

	public abstract TwoWheeler getTwoWheeler(Model model, Color color, int registrationNo);

	public abstract FourWheeler getFourWheeler(Model model, Color color, int registrationNo);

}

 

Step 6

Create specific Factory classes extending AbstractVehicleFactory to generate Objects of concrete Car and Bike classes based on given Model and Color information.

TwoWheelerFactory.java

package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class TwoWheelerFactory extends AbstractVehicleFactory {

	@Override
	public TwoWheeler getTwoWheeler(Model model, Color color, int registrationNo) {
		if (model == null || color == null || registrationNo == 0) {
			throw new RuntimeException("Invalid TwoWheeler creation request");
		}
		TwoWheeler twoWheeler = null;
		if (model.equals(Model.Pulsar)) {
			twoWheeler = new Pulsar(registrationNo);
		} else if (model.equals(Model.Duke)) {
			twoWheeler = new Duke(registrationNo);
		} else if (model.equals(Model.Apache)) {
			twoWheeler = new Apache(registrationNo);
		}
		twoWheeler.setColor(color);
		return twoWheeler;
	}

	@Override
	public FourWheeler getFourWheeler(Model model, Color color, int registrationNo) {
		return null;
	}

}

FourWheelerFactory.java
package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class FourWheelerFactory extends AbstractVehicleFactory {

	@Override
	public TwoWheeler getTwoWheeler(Model model, Color color, int registrationNo) {
		return null;
	}

	@Override
	public FourWheeler getFourWheeler(Model model, Color color, int registrationNo) {
		if (model == null || color == null || registrationNo == 0) {
			throw new RuntimeException("Invalid FourWheeler creation request");
		}
		FourWheeler fourWheeler = null;
		if (model.equals(Model.Bmw)) {
			fourWheeler = new BMW(registrationNo);
		} else if (model.equals(Model.Audi)) {
			fourWheeler = new Audi(registrationNo);
		} else if (model.equals(Model.Mercedes)) {
			fourWheeler = new Mercedes(registrationNo);
		}
		fourWheeler.setColor(color);
		return fourWheeler;
	}
}

 

Step 7

Create a Factory generator/producer class to get factories by passing an information such as FourWheeler or TwoWheeler

FactoryProducer.java

package com.tuturself.abstractfactory;

public class FactoryProducer {
	
	public static AbstractVehicleFactory getFactory(String choice) {
		if (choice.equalsIgnoreCase("FourWheeler")) {
			return new FourWheelerFactory();
		} else if (choice.equalsIgnoreCase("TwoWheeler")) {
			return new TwoWheelerFactory();
		}
		return null;
	}
}

 

Step 8

Use the FactoryProducer to get AbstractVehicleFactory in order to get factories of concrete classes by passing an information such as type.

AbstractFactoryPatternDemo.java

package com.tuturself.abstractfactory;

import com.tuturself.abstractfactory.Configuration.Color;
import com.tuturself.abstractfactory.Configuration.Model;

public class AbstractFactoryPatternDemo {
	public static void main(String[] args) {

		FourWheeler car = null;
		TwoWheeler bike = null;

		// get FourWheeler factory
		AbstractVehicleFactory fourWheelerFactory = 
                                  FactoryProducer.getFactory("FourWheeler");

		// Lets get a Red BMW
		car = fourWheelerFactory.getFourWheeler(Model.Bmw, Color.Red, 1234);
		car.display();

		// Lets get a Blue BMW
		car = fourWheelerFactory.getFourWheeler(Model.Bmw, Color.Blue, 3456);
		car.display();

		// Lets get a Silver Audi
		car = fourWheelerFactory.getFourWheeler(Model.Audi, Color.Silver, 1234333);
		car.display();

		// Lets get a Purple Mercedes
		car = fourWheelerFactory.getFourWheeler(Model.Mercedes, Color.Purple, 1234);
		car.display();

		// get TwoWheeler factory
		AbstractVehicleFactory twoWheelerFactory = 
                                           FactoryProducer.getFactory("TwoWheeler");

		// Lets get a Blue Pulsar
		bike = twoWheelerFactory.getTwoWheeler(Model.Pulsar, Color.Blue, 3456333);
		bike.display();

		// Lets get a Silver Apache
		bike = twoWheelerFactory.getTwoWheeler(Model.Apache, Color.Silver, 1234333234);
		bike.display();

		// Lets get a Red Duke
		bike = twoWheelerFactory.getTwoWheeler(Model.Duke, Color.Red, 123412);
		bike.display();
	}
}

 

Step 9

Verify the output.

--------- FourWheeler ---------
Registration No: 1234
Model: Bmw
Color: Red
--------- FourWheeler ---------
Registration No: 3456
Model: Bmw
Color: Blue
--------- FourWheeler ---------
Registration No: 1234333
Model: Audi
Color: Silver
--------- FourWheeler ---------
Registration No: 1234
Model: Mercedes
Color: Purple
--------- TwoWheeler ---------
Registration No: 3456333
Model: Pulsar
Color: Blue
--------- TwoWheeler ---------
Registration No: 1234333234
Model: Apache
Color: Silver
--------- TwoWheeler ---------
Registration No: 123412
Model: Pulsar
Color: Red

 

core java 12

FOLLOW US ON LinkedIn



Explore Tutu'rself