Factory design pattern using Java annotation, IoC and Springboot

Factory pattern is a creational pattern where the logic of creating an object of the class resides in a factory class, in this article, we will see how to implement a factory pattern that always returns a new instance of the class ( prototype scope) in Springboot

Will take a simple and common example for the factory design pattern, draw the shape. We have an interface shape and multiple implementations of the shape let say Square and Rectangle classes and a factory method which will get the name of the shape as an argument and return the object of the shape using if / switch. this is the usual way of implementing the factory pattern in Core Java. In Springboot with the dependency injection ( IoC ) the objects are created and injected automatically. we will see how to create a new object every time and implement the factory pattern.

First we create an interface shape

public interface Shape {
  String draw();
}

Enum for Shapes

Then we will create an ENUM of shapes which we will be used for annotating the Shape implementation

public enum ShapesType {
  SQUARE,
  RECTANGLE
}

Annotation for the Shapes

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Shapes {

  ShapesType[] command();

}

We created this annotation class to use it in all the implementation of the Shapes Interface, this annotation will help the factory to identify which class to use for each shape type. Here in ShapeTypes I use array, this will be helpful in some use cases like Square and Rectangle we can use the same implementation class

Then we will have two implementation Square and Rectangle

Square Implementation

@Shapes(command = SQUARE)
@Service
@Scope(value = "prototype")
public class SquareImplementation implements Shape {
  @Override
  public String draw() {
    return Integer.toHexString(System.identityHashCode(this));
  }
}

Rectangle Implementation

@Service
@Shapes(command = RECTANGLE)
@Scope(value = "prototype")
public class RectangleImplementation implements Shape {
  @Override
  public String draw() {
    return Integer.toHexString(System.identityHashCode(this));
  }
}

Shape Factory

In this factory, the handler is @Autowired , while loading the application all the implementation of the shape interface is populated in the handlers variable

  @Autowired
  private ShapeFactory(List<Shape> handlers) {
    this.handlers = handlers;
  }

And in @PostConstruct , we fetch the annotation of all the handlers and use that shape as a key and the handler object as the value.

  @PostConstruct
  public void initMyServiceCache() {
    handlers.forEach(service -> {
      Shapes annotation = service.getClass().getAnnotation(Shapes.class);
      ShapesType[] commands = annotation.command();
      for (ShapesType command : commands) {
        myServiceCache.put(command, service);
      }
    });
  }

A method getShapeImplementation which uses the map and get the value from the Key of shapes

  public static Shape getShapeImplementation(ShapesType shapesType) {

    Shape service = myServiceCache.get(shapesType);
    if (null == service) {
      throw new RuntimeException("Unknown shape type: " + shapesType);
    }
    return FactoryUtil.getBean(service.getClass());
  }

In this, there is a class called FactoryUtil and has a method getBean which is used to get the new instance of the Shape class whenever it gets invokes using the Springboot Application Context-Aware implementation, read more about the scoped bean injection problem here.

@Service
public class FactoryUtil implements ApplicationContextAware {

  private static ApplicationContext context;

  public FactoryUtil() {
  }

  public static <T> T getBean(Class<T> beanClass) {
    return context.getBean(beanClass);
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    context = applicationContext;
  }
}

Take away

In this article, we have seen the ways to use the Spring bean dependency injection and the prototype scope to create a new object of the implementation class for the factory design pattern, if you have hundreds of shapes also the code remains the same and you need to add more ENUM and shape implementation, no need to keep adding an if statements or the cases to the switch.

The full example of this code you can be found in my GitHub repository

https://github.com/asvignesh/springbootfactory


Also published on Medium.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from

Subscribe now to keep reading and get access to the full archive.

Continue reading