Ways to refactor Switch Statements

Hi Folks,

When we do coding it is very general practice to use switch statements if we have multiple actions and want to perform one action on the basis of some conditions or some type.

Switch statements are good to use as it shows different responsibilities for different case but it may lead to a long method if it has more than 10 cases and every case has approx. six to seven lines of code.

In this scenario, we should rethink or refactor switch statements in Object oriented way so that our code looks cool, clean and it could add some abstraction into the implementation level.

There can be many ways in which we can refactor switch cases. Today we’ll  discuss some ways out of them.

Let’s take an example of simple switch case which we will improve with multiple approaches.

Let say we have to generate random things on the basis of random type so in order to do this we’ll have following switch statements:

public Object getRandomString(String randomType)
{
    switch(randomType)
    {
        case "RANDOM_NUMBER":
            //TODO - random number code generation goes here
            break;
        case "RANDOM_STRING":
            //TODO - RANDOM_STRING code generation goes here
            break;
        case "CURRENT_DATE":
            //TODO - CURRENT_DATE code generation goes here
            break;
        case "CURRENT_TIME":
            //TODO - CURRENT_TIME code generation goes here
            break;
        case "TIMESTAMP":
            //TODO - TIMESTAMP code generation goes here
            break;
        case "UUID":
            //TODO - UUID code generation goes here
            break;
            default:
                throw new IllegalArgumentException("Invalid random type");
    }

    return null;
}

Use of Enum:

The most common way to improve above switch statement is use Enum as below:
Write a enum for each case and create an abstract method in it to generate random string and override it in every enum as below:

public enum BuiltInEnum {

	TIMESTAMP // Generate Timestamp
	{
		@Override
		public Object generateRandomString() {
			//TODO implemenation goes here
			return null;
		}
	},
	CURRTIME // Generate current time
	{
		@Override
		public Object generateRandomString() {
			//TODO implemenation goes her
			return null;
		}
	},
	CURRDATE // generate current date
	{
		@Override
		public Object generateRandomString() {
			//TODO implemenation goes her
			return null;
		}
	},
	RANDOM_STRING //generate random string
	{
		@Override
		public Object generateRandomString() {
			//TODO implemenation goes her
			return null;
		}
	},
	RANDOM_NUMBER //generate random number
	{
		@Override
		public Object generateRandomString() {
			//TODO implemenation goes her
			return null;
		}
	};

	public abstract Object generateRandomString();
}

Now invoke the enum to generate random string on the basis of random type as below:

public static void main(String[] args) throws ScriptException {
        Object randomString = BuiltInEnum.valueOf("RANDOM_NUMBER").generateRandomString();
        System.out.println(randomString);
}

As you can see that we have removed all the cases with Enum.

Use of Strategy pattern:

As we all know design patterns help us to write clean and manageable code. We can also use strategy pattern in order to refactor switch statements.

Strategy Design Pattern is also known as Policy Desing Pattern. We define multiple algorithms and let client application pass the algorithm to be used as a parameter.

One of the best example of strategy pattern is Collections.sort() method that takes Comparator parameter. Based on the different implementations of Comparator interfaces, the Objects are getting sorted in different ways.

To know more about the pattern read.

In order to use strategy pattern we firstly need to define an interface to generate random string as below:

public interface RandomStrGenerator {

    Object generateRandomString();
}

Now this interface will have different implementation classes for every cases as below:


//Class to generate random String
public class RandomStringGenerator implements RandomStrGenerator{

    @Override
    public Object generateRandomString() {
        //TODO - implementation goes here
        return null;
    }
}

//class to generate random number
public class RandomNumberGenerator implements RandomStrGenerator{

    @Override
    public Object generateRandomString() {
        //TODO - implementation goes here
        return null;
    }
}

//Class to generate current date
public class CurrentDateGenerator implements RandomStrGenerator{

    @Override
    public Object generateRandomString() {
        //TODO - implementation goes here
        return null;
    }
}

It’s time to use above pattern in order to generateRandomString.

import java.util.HashMap;
import java.util.Map;

public class TestGenerator {

    static  Map randomStrGeneratorMap = new HashMap();
    static {
        randomStrGeneratorMap.put("RANDOM_STRING", new RandomStringGenerator());
        randomStrGeneratorMap.put("RANDOM_NUMBER", new RandomNumberGenerator());
        randomStrGeneratorMap.put("CURRENT_DATE", new CurrentDateGenerator());
    }

    public static void main(String[] arg)
    {
        RandomStrGenerator randomStrGenerator = randomStrGeneratorMap.get("RANDOM_STRING");
        Object randomString = randomStrGenerator.generateRandomString();
        System.out.println(randomString);
    }
}

As you can see how we can use strategy pattern in order to refactor switch case.

In similar way, we can optimise if/else statements.

This was a small example but in real scenarios we have many more cases and have different kind of implementation for each case so it is best to use design patterns rather than use of legacy implementation by use switch case.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s