Java programming language logo

Factory Method Design Pattern

The Factory Method pattern provides a way for creating objects without specifying the concrete type of them.

Factory Method defines a method for creating objects, which is overridden by subclasses. The subclasses decide which type of objects get instantiated.

Factory Method is a creational pattern.

Factory Method Pattern vs. Abstract Factory Pattern

Factory Method relies on inheritance (incl. interface implementation). It delegates the object creation to subclasses.

Abstract Factory relies on object composition. It delegates the object creation to another object.

The Factory Method is a method that can be overridden by subclasses. Abstract Factory is an object that has multiple factory methods.

Both patterns encapsulate and hide the object creation logic. The type of the created objects are determined at run-time.

Example

In the next Java example, we are going to instantiate different types of cars. For now a car can be a petrol car or an electric car, and both of them can be real or cartoon.

The abstract Car class is the base class of all cars. It has four fields, which get values by the subclasses. The subclasses also override its abstract create method.


package com.programcodex.designpatterns.factorymethod;

public abstract class Car {

    protected String carType;
    protected String engine;
    protected String energyStorage;
    protected String gearbox;

    public abstract void create();

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("\n### ");
        sb.append(carType).append(" car ###")
        .append("\nEngine: ").append(engine);

        if (energyStorage != null) {
            sb.append("\nEnergy storage: ").append(energyStorage);
        }

        if (gearbox != null) {
            sb.append("\nGearbox: ").append(gearbox);
        }

        return sb.toString();
    }
}

The PetrolCar class extends the Car class and represents a real petrol car. In the create method it gives values to the four fields, which are defined in the base class.


package com.programcodex.designpatterns.factorymethod;

public class PetrolCar extends Car {

    @Override
    public void create() {
        carType = "Petrol";
        engine = "Petrol engine";
        energyStorage = "Fuel tank";
        gearbox = "Automatic";
    }
}

The ElectricCar class also extends the Car class and represents a real electric car. In the create method, it gives values to the fields, which are defined in the base class, but this class doesn’t provide value for the gearbox field because electric cars don’t have gearboxes.


package com.programcodex.designpatterns.factorymethod;

public class ElectricCar extends Car {

    @Override
    public void create() {
        carType = "Electric";
        engine = "Electric motor";
        energyStorage = "Battery";
    }
}

Now come the cartoon versions of the cars. Obviously, cartoon cars are much simpler than real ones, so they have less fields. The CartoonPetrolCar only uses two fields in the create method.


package com.programcodex.designpatterns.factorymethod;

public class CartoonPetrolCar extends Car {

        @Override
        public void create() {
            carType = "Cartoon Petrol";
            engine = "Petrol engine";
        }
}

Just like the previous class, the CartoonElectricCar class gives values only to two fields.


package com.programcodex.designpatterns.factorymethod;

public class CartoonElectricCar extends Car {

    @Override
    public void create() {
        carType = "Cartoon Electric";
        engine = "Electric motor";
    }
}

Now we have a lot of car objects. Next we need factories to instantiate the appropriate ones. The Factory interface defines the signature of factory method.


package com.programcodex.designpatterns.factorymethod;

public interface Factory {

    public Car createCar(String type);
}

There will be two factory classes. One of them is responsible for creating real cars, the other is responsible for creating cartoon cars.

The CarFactory class implements the Factory interface and produces real cars. The createCar method has a type parameter. The type can be petrol or electric. This method hides the object creation logic. It instantiates a kind of Car and calls its create method. After that, the new object is returned to the caller, who doesn’t know the exact type of the object. It only knows it’s a kind of Car. So in Factory Method pattern the objects are loosely coupled.


package com.programcodex.designpatterns.factorymethod;

public class CarFactory implements Factory {

    @Override
    public Car createCar(String type) {
        Car car = null;
        
        if ("petrol".equals(type)) {
            car = new PetrolCar();
        } else if ("electric".equals(type)) {
            car = new ElectricCar();
        }
        
        car.create();
        
        return car;
    }
}

The CartoonCarFactory class is almost the same as the CarFactory class, but this one instantiates cartoon cars.


package com.programcodex.designpatterns.factorymethod;

public class CartoonCarFactory implements Factory {

    @Override
    public Car createCar(String type) {
        Car car = null;
        
        if ("petrol".equals(type)) {
            car = new CartoonPetrolCar();
        } else if ("electric".equals(type)) {
            car = new CartoonElectricCar();
        }
        
        car.create();
        
        return car;
    }
}

And we are done. It’s time to run these things.

The createCars method receives a Factory instance as an argument, which can be CarFactory or CartoonCarFactory. It doesn’t know the exact type of the factory, but with the help of it, it creates a petrol and an electric car.

From the main method, the createCars method is called twice. Once with a CarFactory instantiate and once with a CartoonCarFactory instance.


package com.programcodex.designpatterns.factorymethod;

public class TestFactoryMethod {

    public static void main(String[] args) {
        Factory factory;
        
        factory = new CarFactory();
        createCars(factory);
        
        factory = new CartoonCarFactory();
        createCars(factory);
    }
    
    private static void createCars(Factory factory) {
        Car car = factory.createCar("petrol");
        System.out.println(car);
        
        car = factory.createCar("electric");
        System.out.println(car);
    }
}

The output of the above test class:

The Factory Method Design Pattern