Interpreter Pattern in Java
In the **Interpreter Pattern**, the **Interpreter Context Engine** (often just called the **Context**) provides the context in which expressions are evaluated or interpreted.
Explanation: The Interpreter pattern defines a grammatical representation for a language and provides a way to interpret sentences or statements in that language. The **Context Engine** is essentially a data structure or environment that holds all the relevant information that the expressions (interpreters) require to perform interpretation.
Typical responsibilities of the Interpreter Context Engine:
- Storing variables and their values:
Keeps track of variables and their bindings during interpretation.
- Managing state or environment:
Provides a reference for expressions that require state information during interpretation.
- Facilitating communication between expressions:
Enables different parts of the interpreter to access shared resources or results.
- Caching or storing intermediate results:
Improves performance by avoiding redundant evaluations.
Example (Simplified Java Implementation):
Here's a simplified Java example of an **Interpreter Context Engine**:
import java.util.HashMap;
import java.util.Map;
// Interpreter Context Engine
public class InterpreterContext {
private Map<String, Integer> variables;
public InterpreterContext() {
variables = new HashMap<>();
}
public void setVariable(String name, Integer value) {
variables.put(name, value);
}
public Integer getVariable(String name) {
return variables.get(name);
}
}
// Expression interface
interface Expression {
int interpret(InterpreterContext context);
}
// Concrete expression implementation
class VariableExpression implements Expression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
@Override
public int interpret(InterpreterContext context) {
Integer value = context.getVariable(name);
if (value == null) {
throw new RuntimeException("Undefined variable: " + name);
}
return value;
}
}
Usage:
InterpreterContext context = new InterpreterContext();
context.setVariable("x", 10);
context.setVariable("y", 20);
Expression exprX = new VariableExpression("x");
Expression exprY = new VariableExpression("y");
System.out.println(exprX.interpret(context)); // outputs 10
System.out.println(exprY.interpret(context)); // outputs 20
Key points:
- The Interpreter Context Engine provides necessary information for expression evaluation.
- It stores state, context, or shared information needed by interpreter classes.
- It separates the interpretation logic from data management, leading to cleaner, more maintainable code.
This design simplifies complex parsing and interpretation tasks, especially useful when interpreting custom languages or evaluating logical/arithmetic expressions in Java.
In order to implement the
Interpreter Pattern, we need to
- create the Interpreter context engine that will do the interpretation work.
- create different Expression implementations that will consume the functionalities provided by the Interpreter Context.
- create the client that will take the input from user and decide which Expression to use and then generate output for the user.
InterpreterContext
package com.java.behavioral.interpreter;
public class InterpreterContext {
public String getBinaryFormat(int i){
return Integer.toBinaryString(i);
}
public String getHexadecimalFormat(int i){
return Integer.toHexString(i);
}
}
Now we need to create different types of Expressions that will consume the interpreter context class.
package com.java.behavioral.interpreter;
public interface Expression {
String interpret(InterpreterContext ic);
}
We will have two Expression implementations,
- one to convert int to binary and
- the other to convert int to hexadecimal format.
package com.java.behavioral.interpreter;
public class IntToBinaryExpression implements Expression {
private int i;
public IntToBinaryExpression(int c){
this.i=c;
}
@Override
public String interpret(InterpreterContext ic) {
return ic.getBinaryFormat(this.i);
}
}
package com.java.behavioral.interpreter;
public class IntToHexExpression implements Expression {
private int i;
public IntToHexExpression(int c){
this.i=c;
}
@Override
public String interpret(InterpreterContext ic) {
return ic.getHexadecimalFormat(i);
}
}
Create the client application that will have the logic to parse the user input and pass it to the correct expression and then use the output to generate the user response.
package com.java.behavioral.interpreter;
public class InterpreterClient {
public InterpreterContext ic;
public InterpreterClient(InterpreterContext i){
this.ic=i;
}
public String interpret(String str){
Expression exp=null;
//create rules for expressions
if(str.contains("Hexadecimal")){
exp=new IntToHexExpression(Integer.parseInt(str.substring(0,str.indexOf(" "))));
}else if(str.contains("Binary")){
exp=new IntToBinaryExpression(Integer.parseInt(str.substring(0,str.indexOf(" "))));
}else return str;
return exp.interpret(ic);
}
public static void main(String args[]){
String str1 = "17 in Binary";
String str2 = "17 in Hexadecimal";
InterpreterClient ec = new InterpreterClient(new InterpreterContext());
System.out.println(str1+"= "+ec.interpret(str1));
System.out.println(str2+"= "+ec.interpret(str2));
}
}
The client also has a main method for testing purpose, when we run above we get following output:
17 in Binary= 10001
17 in Hexadecimal= 11
Interpreter Pattern Diagram
