The Factory Method, also known as Factory Pattern is one of the most commonly used design patterns in object-oriented programming (OOP). Factory Method allows us to separate the object-creation logic from the application, by providing an application-independent object the responsibility to create application-specific objects. This essentially adds a middle layer between the application logic and the object creation, hence decoupling the two.

Structure

The main idea behind the Factory Method is to define an interface (or abstract class) for creating objects, but let the subclasses decide which object to instantiate. The Factory Method pattern consists of the following roles:

  • Product: this is a superclass or an interface for the objects that are produced by the Factory Method pattern
  • Concrete Products: these are concrete classes that implement the Product interface
  • Creator: this is an interface that declares a factory method that returns objects of Product type. The return type of the factory method must be the same as the Product class. A default implementation of the factory method can be provided which returns a default ConcreteProduct object
  • Concrete Creators: this is a class that implements the appropriate factory, and the factory method returns objects of the ConcreteProduct type
  • Client: uses factory method from a concrete factory to create Product type objects

When to use Factory Pattern?

  • When you want to abstract the object-creation logic in a separate class (Single Responsibility Principle)
  • When you want to add a new type of Product to an application in the future without making too many changes (Open/Closed Principle)
  • The downside to using Factory Pattern, is that code may become more complicated with each new Product added because of the new subclasses used to implement the pattern

Implementation Example

This code demonstrates the implementation of the Factory Method design pattern in Java. The Factory Method pattern provides a way to encapsulate the creation of objects and allows subclasses to decide which class to instantiate.

import java.util.*;

// Client class
public class Solution {

    public static void main(String[] args) {

        List<Creator> creators = new ArrayList<>();
        creators.add(new FirstConcreteCreator());
        creators.add(new SecondConcreteCreator());

        for (Creator creator : creators) {

            Product product = creator.FactoryMethod();
            System.out.println("Created product of type: " + product.getClass());
            product.sayHello();
        }
    }
}

// abstract Product class which can be extended by any new products
abstract class Product {

    public abstract void sayHello();
}

// concrete implementations of the Product class
class FirstConcreteProduct extends Product {

    public void sayHello() {

        System.out.println("Hello from First Concrete Product class!");
    }
}

class SecondConcreteProduct extends Product {

    public void sayHello() {

        System.out.println("Hello from Second Concrete Product class!");
    }
}

// creator which would provide the abstract factory method
// we can define it as an abstract class if we want some methods to provide some basic
// functionality, or make it an interface if we want method definitions only
interface Creator {

    public abstract Product FactoryMethod();
}

// concrete creator class for first product
class FirstConcreteCreator implements Creator {

    public Product FactoryMethod() {

        return new FirstConcreteProduct();
    }

}

// concrete creator class for second product
class SecondConcreteCreator implements Creator {

    public Product FactoryMethod() {

        return new SecondConcreteProduct();
    }
}

The output for the following program is:

Created product of type: class FirstConcreteProduct
Hello from First Concrete Product class!
Created product of type: class SecondConcreteProduct
Hello from Second Concrete Product class!