Use ENUM and map to remove conditional logic in your code.

Using ENUM and a map could be a neat way to remove conditional logic, like switch cases in our code.
Another approach could be to use State design pattern, but if you don’t want to create many classes and your use case is pretty simple and using ENUM will not involve repetition of logic. Then using this approach might not be a bad option.

Let see an example :

suppose we have the class to evaluate Infix Expressions with switch cases :

public class Expression {

    private char op;

    private Expression left;

    private Expression right;

    private int constant;

    public Expression(int constant) {
            this.op = 'c';
            this.constant = constant;
    }

    public Expression(char op, Expression left, Expression right) {
            this.op = op;
            this.left = left;
            this.right = right;
    }

    public int evaluate() {
            switch (op) {
            case 'c':
                    return constant;
            case '+':
                    return left.evaluate() + right.evaluate();
            case '-':
                    return left.evaluate() - right.evaluate();
            case '*':
                    return left.evaluate() * right.evaluate();
            case '/':
                    return left.evaluate() / right.evaluate();
            default:
                    throw new IllegalStateException();
            }
    }

public String  getExpressionDescription() {
    switch (op) {
        case 'c':
            return "Constant";
        case '+':
            return "Addition";
        case '-':
            return "Subtraction";
        case '*':
            return "Multiplication";
        case '/':
            return "Division";
        default:
            throw new IllegalStateException();
    }
}
}

We will make an ENUM class of type ExpressionType and use a map in order to remove switch case logic.
We will override the methods ‘toString’ and ‘evaluate’ for each ENUM type.
In order to get rid of multiple switch cases conditions, we will store the mapping of each ‘operand’ with the corresponding ExpressionType in a map.

The map would get initialised in a static block in the same class and hence we will hide it from the class using it.

public enum ExpressionType {

	ADD {

		@Override
		public String toString() {
			return "ADDITION";
		}

		@Override
		public int evaluate(int left, int right) {
			return left + right;
		}

	},
	SUBTRACT {

		@Override
		public String toString() {
			return "SUBTRACTION";
		}

		@Override
		public int evaluate(int left, int right) {
			return left - right;
		}

	},
	MULTIPLY {

		@Override
		public String toString() {
			return "MULTIPLICATION";
		}

		@Override
		public int evaluate(int left, int right) {
			return left * right;
		}

	},
	DIVIDE {

		@Override
		public String toString() {
			return "DIVISION";
		}

		@Override
		public int evaluate(int left, int right) {
			return left / right;
		}

	};

	private static Map<String, ExpressionType> expressionMap = new HashMap<String, ExpressionType>();
	
	static {
		expressionMap.put(Character.toString('+'), ADD);
		expressionMap.put(Character.toString('-'), SUBTRACT);
		expressionMap.put(Character.toString('*'), MULTIPLY);
		expressionMap.put(Character.toString('/'), DIVIDE);
	}


	public abstract String toString();
	public abstract int evaluate(int left, int right);
	
	public static ExpressionType get(char c) {
		return expressionMap.get(Character.toString(c));
	}
	
	
}

Hence the class Expression becomes :

public class Expression {

	private char op;

	private Expression left;

	private Expression right;

	private int constant;

	public Expression(int constant) {
		this.op = 'c';
		this.constant = constant;
	}

	public Expression(char op, Expression left, Expression right) {
		this.op = op;
		this.left = left;
		this.right = right;
	}

	public int evaluate() {
		if (op == 'c') {
			return constant;
		} else if (ExpressionType.get(op) != null) {
			return ExpressionType.get(op).evaluate(left.evaluate(),
					right.evaluate());
		} else {
			throw new IllegalStateException();
		}
	}

	public String getExpressionDescription() {
		if (op == 'c') {
			return "Constant";
		} else if (ExpressionType.get(op) != null) {
			return ExpressionType.get(op).toString();
		} else {
			throw new IllegalStateException();
		}
	}
}

This simple approach looks quite neat and provides good readability of code.

About these ads
Tagged with:
Posted in design patterns, java
One comment on “Use ENUM and map to remove conditional logic in your code.
  1. Frisian says:

    Three suggestions to make your example more concise:
    - Use a constructor for the enums with the descriptor and the op code (to be stored in private instance variables). Makes the code shorter and adding new ExpressionTypes easier.
    - Iterate over the result from values() inside the static initializer. Any new ExpressionType will be added automagically.
    - The constant opcode ‘c’ can be integrated in expression by adding a method “boolean useConstant()” to the enum, which can be used instead of “op=’c’”

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 112 other followers

%d bloggers like this: