Dynamic Factory Pattern in Java

Advertisements

The Factory Pattern is a widely-used creational design pattern in Java. However, the classic implementation has one major flaw — it violates the Open/Closed Principle from SOLID design. Every time a new type and implementation needs to be added the Factory class must be modified.

Enter Java 8, with its powerful lambda expressions and the Supplier<T> functional interface. These allow us to create a Dynamic Factory Pattern that is more flexible and extensible, keeping our factory class closed for modification and open for extension.

The Problem with Classic Factory Pattern

Let’s begin with a classic example.

Advertisements
interface Shape {
    void draw();
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Square implements Shape {
    public void draw() {
        System.out.println("Drawing a Square");
    }
}

class ShapeFactory {
    public static Shape createShape(String type) {
        switch (type) {
            case "circle": return new Circle();
            case "square": return new Square();
            default: throw new IllegalArgumentException("Unknown shape: " + type);
        }
    }
}

Drawbacks

  • Violation of the Open/Closed Principle: Every new shape requires modifying ShapeFactory.
  • Hard to scale: Over time, the factory becomes a large, monolithic switch statement.
  • Harder to test and maintain.

Dynamic Factory with Lambdas and Supplier

Java 8 introduced the Supplier<T> interface — a perfect fit for factories. It represents a function that supplies an instance of type T. Let’s build a Dynamic Factory that allows registration of new types at runtime, avoiding changes to the factory itself.

1. Define the Interface and Implementations

interface Shape {
    void draw();
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Square implements Shape {
    public void draw() {
        System.out.println("Drawing a Square");
    }
}

2. Create the Dynamic Factory

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

class DynamicShapeFactory {
    private final Map<String, Supplier<Shape>> registry = new HashMap<>();

    public void registerShape(String shapeName, Supplier<Shape> supplier) {
        registry.put(shapeName.toLowerCase(), supplier);
    }

    public Shape createShape(String shapeName) {
        Supplier<Shape> supplier = registry.get(shapeName.toLowerCase());
        if (supplier != null) {
            return supplier.get();
        }
        throw new IllegalArgumentException("Unknown shape: " + shapeName);
    }
}

3. Usage example

public class Main {
    public static void main(String[] args) {
        DynamicShapeFactory factory = new DynamicShapeFactory();

        // Register shapes
        factory.registerShape("circle", Circle::new);
        factory.registerShape("square", Square::new);

        // Create shapes dynamically
        Shape shape1 = factory.createShape("circle");
        Shape shape2 = factory.createShape("square");

        shape1.draw(); // Output: Drawing a Circle
        shape2.draw(); // Output: Drawing a Square
    }
}

Benefits of the Dynamic Factory Pattern

  • Adheres to the Open/Closed Principle: New shapes can be added without modifying DynamicShapeFactory.
  • Extensible at Runtime: You can load and register new types even via configuration files or dependency injection.
  • Easier to Test: You can mock or stub factories by providing custom suppliers in test scenarios.

Conclusion

The Dynamic Factory Pattern in Java, enabled by lambdas and Supplier<T>, is a clean, elegant, and modern alternative to the classic factory approach. It supports better software architecture by reducing coupling, increasing flexibility, and embracing SOLID principles.

While it may introduce a slight upfront complexity due to registration logic, the long-term benefits — especially in scalable and modular applications — make it a powerful design choice.

References

Advertisements

Leave a Reply

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