Creational Design Patterns: Factory

The Factory design pattern illustrated with Java

This is the third part of my series on creational design patterns, we already discussed the Singleton and Builder patterns. It's now time to tackle the Factory pattern, here we go.

The Factory Pattern

This design pattern is one of the most widely used in the Java programming language. The Factory pattern is used to create objects without exposing the instantiation logic to the client. It provides a method of creating objects in a super class but lets the factory class decide which of the subclasses to instantiate. This super class can be an interface, abstract class or a regular class. The subclasses implement/extend the superclass and overrides the superclass's methods with its own implementation of the methods.

This pattern promotes loose coupling by abstracting the object creation process away.

The factory method is particularly useful when we don't know the subclass instance that would be used at runtime

Implementing Factory Method using Java

To implement this, we need the following components

  1. The superclass, it can be an interface/abstract class.

  2. The subclasses that implement/extend the superclass.

  3. The factory class, with decision-making logic to select the subclass to instantiate.

See implementation below:

The superclass, for this example we used an interface.

public interface Polygon {
    int countSides();
}

Subclass implementing the superclass

public class Octagon implements Polygon {
    @Override
    public int countSides() {
        return 8;
    }
}

Another subclass implementing the superclass

public class Pentagon implements Polygon {
    @Override
    public int countSides() {
        return 5;
    }
}

The Factory class where all the magic happens, you can see the if/else decision making structure to determine which subclass is instantiated at runtime.

public class PolygonFactory {
    public Polygon getShape(String shape){
        if(shape.equalsIgnoreCase("Pentagon")){
            return new Pentagon();
        }else if(shape.equalsIgnoreCase("Octagon")){
            return new Octagon();
        }else{
            throw new IllegalArgumentException("Unknown shape");
        }
    }
}

Now let's test out our factory design pattern implementation by implementing the client code.

public class PolygonFactoryDemo {
    public static void main(String [] args){
        Polygon polygon = new PolygonFactory().getShape("Octagon");

        System.out.println("Number of sides in your polygon: "
                                        + polygon.countSides());
    }
}

The outcome of running the above code is:

Number of sides in your polygon: 8

You can see that the client code only interacts with the interface Polygon, rather than the concrete subclass implementation Octagon

Benefits of using the Factory design pattern

Loose coupling: The factory pattern allows for changes to be made to the factory and how objects are created without making changes to the client.

Reusability: By centralizing the creation of objects in a factory, the factory code can be used in different parts of the application.

Conclusion

The factory design pattern is widely used, chances are you have encountered a Factory in Java libraries, this post helps to take a peek into how it is implemented, so we better understand how it works.

The factory design pattern is a powerful tool for creating objects, it helps improve code useability and maintainability.