How to refactor enum to class

In this tutorial we will see how to refactor an enum.  I was recently working on a small project that was using an enum to manage some constants. But we had to change this enum to a class due to change of requirements.

Overview

Let’s say that a project was allowing users to choose from seven colors. But the requirements changed in due course of time and any color could be chosen. So in this situation an enum cannot fulfill the requirement anymore. So we would need to change to class.  In the example below we would define an enum Colors and then a usage class that has some typical use cases of enums.

Classes before refactoring

Colors.java

A simple enum with seven enums. If you are wondering why i have a comment after each enum read Keep formatting enum in IDE

package com.programtalk.learn.enumeration.refactor;

public enum Colors {
	RED, // this is only for keeping the formatting
	ORANGE, //
	YELLOW, //
	GREEN, //
	BLUE, //
	INDIGO , //
	VIOLET;
}

Example usage of Colors

This shows a typical usage of an enum. We are using it in an switch-case and also using == to compare enums.


package com.programtalk.learn.enumeration.refactor;

public class UseColors {

	public void chooseAColor(Colors color ){
		switch (color) {
		case BLUE:
			System.out.println("I have choosen BLUE Color");
			break;
		case GREEN:
		case INDIGO:
		case ORANGE:
		case RED:
		case VIOLET:
		case YELLOW:
			System.out.println("I have choosen " + color + " Color");
			break;
		default:
			break;
		}
	}
	
	public void doSomethingOnly4Yellow(Colors color){
		if(Colors.YELLOW == color){
			System.out.println("Yellow color was selected");
		}
	}
}


 

After Refactoring

Colors Class

So I refactored the enum to a class. So what did i do here?

  • I kept the enums as constants in the Colors class. This i did so that i don’t have to change the code lines that refer to the constants. Colors.RED will still work.
  • I used the factory method to create the instance of the Object
  • I implemented the equals() and hashCode() so that the objects are equal only when the color is the same.

package com.programtalk.learn.enumeration.refactored;

import org.apache.commons.lang3.StringUtils;

public class Colors {
	public static final Colors RED =  Colors.create("RED"); 
	public static final Colors ORANGE =  Colors.create("ORANGE"); //
	public static final Colors YELLOW =  Colors.create("YELLOW"); //
	public static final Colors GREEN =  Colors.create("GREEN"); //
	public static final Colors BLUE =  Colors.create("BLUE"); //
	public static final Colors INDIGO =  Colors.create("INDIGO"); //
	public static final Colors VIOLET =  Colors.create("VIOLET"); //
	
	private final String color;
	
	public static Colors create(String color) {
		if(StringUtils.isBlank(color)){
			throw new IllegalStateException("color must not be blank");
		}
		return new Colors(color);
	}
	
	private Colors(){
		throw new IllegalStateException("Please use another constructor.");
	}
	
	private Colors(String color) {
		this.color = color;
	}

	public String getColor() {
		return color;
	}

	/**
	 * It is important to have the equals and hashcode functions implemeted
	 * 
	 */
	@Override
	public int hashCode() {
		return 17 + color.hashCode();
	}
	@Override
	public boolean equals(Object obj) {
		if(obj == null){
			return false;
		}
		if(!(obj instanceof Colors)){
			return false;
		}
		Colors otherColor = (Colors) obj;
		return StringUtils.equals(this.getColor(), otherColor.getColor());
	}
}


 

Example usage of Colors class

In the example I changed the following pieces of code

  • In the switch-case I had to change to string constants
  • And the == has to be changed to equals()

package com.programtalk.learn.enumeration.refactored;


public class UseColors {

	public void chooseAColor(Colors color ){
		switch (color.getColor()) {
		case "BLUE":
			System.out.println("I have choosen BLUE Color");
			break;
		case "GREEN":
		case "INDIGO":
		case "ORANGE" :
		case "RED" :
		case "VIOLET" :
		case "YELLOW" :
			System.out.println("I have choosen " + color + " Color");
			break;
		default:
			break;
		}
	}
	/**
	 * While refactoring take care that equals is replaced with equals()
	 * @param color
	 */
	public void doSomethingOnly4YellowWrong( Colors color){
		// doesnot show a compiler warning but may work only when you pass the Colors.YELLOW  object
		if(Colors.YELLOW == color){
			System.out.println("Yellow color was selected");
		}
	}
	
	/**
	 * While refactoring take care that equals is replaced with equals()
	 * @param color
	 */
	public void doSomethingOnly4YellowCorrect( Colors color){
		// this will always work
		if(Colors.YELLOW.equals(color)){
			System.out.println("Yellow color was selected");
		}
	}
	
}


Like this post? Don’t forget to share it!

Leave a Reply

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