Interpreter Pattern Design Patterns in Java

Interpreter pattern provides a way to evaluate language grammar or expression. The term interpreter means a person who interprets the stuff in a foreign language into a language that is understandable. In the terms of computer programming, an interpreter is a pattern in which the programming language is evaluated line by line. This type of pattern comes under behavioral pattern of the 23 GoF Design Patterns.

Interpreter pattern

According to the Gang of Four:

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

Behavioral pattern is a design pattern through which common communication patterns are identified between different objects. This way the communication is carried out in more flexible way. The areas of use of this design pattern of the interpreter are symbol processing engine, SQL parsing etc.

UML class diagram for Interpreter Design Pattern

There is a following UML diagram illustrates about this patterns and its components.

Interpreter Pattern
Benefits of Interpreter Pattern

The following lists the benefits of using the Interpreter pattern:

  • This pattern allows you to change and extend the grammar easily.
  • Using the expression language is very easy

Steps to Implementation for this Pattern

Here are the following steps for the implementation of the interpreter.

Step 1: AbstractExpression (Expression)

The first step for the implementation of the interpreter is the creation of the expression interface “Expression.java”.

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public abstract class Expression {
	
	public void Interpret(Context context){
		if (context.get_input().length() == 0)
			return;
		if (context.get_input().startsWith(nine())) {
			context.set_output(context.get_output()+ 9 * multiplier());
			context.set_input(context.get_input().substring(2));
		}else if (context.get_input().startsWith(four())){
			context.set_output(context.get_output()+ 4 * multiplier());
			context.set_input(context.get_input().substring(2));
		}else if (context.get_input().startsWith(five())){
			context.set_output(context.get_output()+ 5 * multiplier());
			context.set_input(context.get_input().substring(1));
		}

		while (context.get_input().startsWith(one())){
			context.set_output(context.get_output()+ 1 * multiplier());
			context.set_input(context.get_input().substring(1));
		}
	}

	public abstract String one();

    public abstract String four();

    public abstract String five();

    public abstract String nine();

    public abstract int multiplier();
}

Step 2: TerminalExpression ( ThousandExpression, HundredExpression, TenExpression, OneExpression )

After the creation of the interface or abstract, the second step is to use the created interface to create concrete classes.

ThousandExpression.java

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public class ThousandExpression extends Expression {

	@Override
	public String one() {
		return "M";
	}

	@Override
	public String four() {
		return " ";
	}

	@Override
	public String five() {
		return " ";
	}

	@Override
	public String nine() {
		return " ";
	}

	@Override
	public int multiplier() {
		return 1000;
	}
}

HundredExpression.java

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public class HundredExpression extends Expression {

	@Override
	public String one() {
		return "C";
	}

	@Override
	public String four() {
		return "CD";
	}

	@Override
	public String five() {
		return "D";
	}

	@Override
	public String nine() {
		return "CM";
	}

	@Override
	public int multiplier() {
		return 100;
	}

}

TenExpression.java

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public class TenExpression extends Expression {

	@Override
	public String one() {
		return "X";
	}

	@Override
	public String four() {
		return "XL";
	}

	@Override
	public String five() {
		return "L";
	}

	@Override
	public String nine() {
		return "XC";
	}

	@Override
	public int multiplier() {
		return 10;
	}

}

OneExpression.java

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public class OneExpression extends Expression {

	@Override
	public String one() {
		return "I";
	}

	@Override
	public String four() {
		return "IV";
	}

	@Override
	public String five() {
		return "V";
	}

	@Override
	public String nine() {
		return "IX";
	}

	@Override
	public int multiplier() {
		return 1;
	}

}

Step 3: Context (Context.java)

It contains information that is global to the interpreter

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

/**
 * @author Dinesh.Rajput
 *
 */
public class Context {
	private String _input;
	private int _output;
	
	public Context(String _input) {
		super();
		this._input = _input;
	}
	public String get_input() {
		return _input;
	}
	public void set_input(String _input) {
		this._input = _input;
	}
	public int get_output() {
		return _output;
	}
	public void set_output(int _output) {
		this._output = _output;
	}
	
}

Step 4: Let’s create Interpreterpatterndemo.java file using the expression class to create rules and then parse them.

/**
 * 
 */
package com.doj.patterns.behavior.interpreter;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Dinesh.Rajput
 *
 */
public class InterpreterPatternDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String roman = "MMCDXXVIIVI";
		Context context = new Context(roman);

		// Build the 'parse tree'
		List tree = new ArrayList<>();
		tree.add(new ThousandExpression());
		tree.add(new HundredExpression());
		tree.add(new TenExpression());
		tree.add(new OneExpression());
		
		// Interpret
		for (Expression exp : tree){
			exp.Interpret(context);
		}
		System.out.println(roman+" = "+context.get_output());
	}

}

Step 5: The fifth and the final step is to verify the output.

MMCDXXVIIVI = 2427
Previous
Next