Using enums as implementions for an interface, how and where it can be helpful !!

Malkeith Singh
3 min readSep 13, 2020

--

Interfaces help us in writing losely coupled code which is easily extendable. We all have heard the term “code to interfaces not classes” and I make a habit to abide by it. They form the basis of almost all design patterns and classes usually provide their concrete implementations. But as we are going to see today we can also use enums instead. And there are scenerions where they provide a much better fit.

Lets quickly look at one of them:

Lets say you have interface which provides various configurations for an object. Lets call it Configuration.

public interface Configuration {  String foo();  String bar();
}

Now lets say your object can have 50 such configurations. How would you approach it ? Ideally you would:

  • Create a class for each one and put them in an appropriately named package.
  • Then create a factory class which would return you the correct implementation based on a value.

This would look something like this:

Class Conf1 implements Configuration {    @Override
public String foo(){
return "foo";
}

@Override
public String bar(){
return "bar";
}
}
// 49 more such classes which you would then keep in a package// The factory classpublic ConfigurationFactory {public static Configuration getConf(String config){ switch(config){
case "conf1":
return new Conf1;
// rest of the code
}
}
}

But if you use an enum instead. Your code will look something like this:

public enum ObjectConfigurations implements Configuration {

CONF1("foo", "bar");
//49 more configurations
ObjectConfigurations(String foo, String bar) {
this.foo = foo;
this.bar = bar;
}
String foo;
String bar;
@Override
public String foo() {
return foo;
}
@Override
public String bar() {
return bar;
}
// Method to return configuration object based on the name
public static Optional<Configuration> getConfiguration(String conf) {
return Arrays.stream(ObjectConfigurations.values()).filter(x -> x.name().equalsIgnoreCase(conf))
.map(x -> (Configuration) x).findFirst();
}
}

See how the enum has made our life easier. Even the factory method is in the same enum and unlike the factory method in a class we don’t have to touch it whenever a new configuration is introduced, it automatically handles it. Also it creates a singleton object by default so you don’t have to worry about multiple configuration objects littering your heap memory.

If 50 objects per enum seems a lot you can always split them into multiple enums. Each enum representing a group of configurations.

Note: I have a taken a very trivial example interface here. But the interface can be as complex as you want, the concept remains the same.

I have personally used it extensively while implementing strategy pattern, template pattern etc and it has made my code more robust, readable and less prone to errors.

If you found this article helpful you can support me by following me, you can also buy me a coffee here . Also, let me know what you would like me to write about next.

Hope this comes in handy. Untill next time.

--

--

Malkeith Singh

Malkeith is a web developer with a stronger affinity towards backend development. He Loves designing and developing backend systems for the web.