Factory pattern using enum

Enums are powerful

Industrial building vector created by storyset - www.freepik.com

Disclaimer : The content of this blog are my views and understanding of the topic. I do not intend to demean anything or anyone. I am only trying to share my views on the topic so that you will get a different thought process and angle to look at this topic.

Introduction

I was watching a Devoxx talk by Victor Rentea, in which he introduced the thought process of empowering enums. I used that concept and applied it to the Factory Design Pattern. Factory design pattern enables us to create instances of similar types. You request for the type of object you want and factory will instantiate it for you. It enables us to centralise the object creation. We know the typical factory pattern using a switch case, but I am going to introduce you to new way which is based on Enums. 

Example

Consider that you have a Parser interface which is implemented by XmlParser and JsonParser classes. Now you want to get an instance of a particular parser from the Factory.

Switch Case based Factory

In this case you will have a switch case which will return a particular instance based on the Type you request.

public interface Factory {

   static Parser getInstance(ParserType parserType) {

       return switch (parserType) {

           case XML -> new XmlParser();

           case JSON -> new JsonParser();

       };

   }

}

public interface Parser {

   void parse();

}

public enum ParserType {

   XML, JSON

}

public class JsonParser implements Parser {


   @Override

   public void parse() {

       System.out.println("Invoked Json Parser");

   }

}

public class XmlParser implements Parser {


   @Override

   public void parse() {

       System.out.println("Invoked XML Parser");

   }

}

Now if you want to introduce a new type or parser ( Ex: HTML ) then you need to add a new value in the enum. Also you will need to update the Factory to return the instance of that HtmlParser class ( i.e. add a new case in the switch case ).

Enum based Factory

What if we could leverage some cool features of enum and Java functional programming concepts and convert the enum into a factory. The new approach would be like shown below :

public enum ParserType {


   XML(XmlParser::new), JSON(JsonParser::new);


   public final Supplier<Parser> instanceSupplier;


   ParserType(Supplier<Parser> instanceSupplier) {

       this.instanceSupplier = instanceSupplier;

   }


}


We refactored the enum to have a parameterised constructor, which accepts the Supplier of the Parser instance. Functional programming in java enables us to treat constructors as supplier. So now we added them in the enum class. Which means we now localised the change in the Enum class and converted it into a Factory.

When you want a specific instance you talk to the enum type directly and request for the instance it represents as shown in the ParserDemo class.

public class ParserDemo {


   public static void main(String[] args) {

       ParserType.JSON.instanceSupplier.get().parse();

       ParserType.XML.instanceSupplier.get().parse();

   }


}


Summary

Enums are powerful on their own but when clubbed with functional programming concepts they can work wonders. What could we do more ? It only takes mixing different features and see. Knowledge is limited by the amount of efforts you put in to find alternative solutions.

It is rightly said by Shuri in the Black Panther movie : 

Only because something works does not mean it cannot be improved.