Easy Tutorial
❮ Composite Entity Pattern Intercepting Filter Pattern ❯

Interpreter Pattern

The Interpreter Pattern provides a way to evaluate the syntax or expressions of a language, and it belongs to the behavioral pattern category. This pattern implements an expression interface that interprets a specific context. It is used in SQL parsing, symbol processing engines, etc.

Introduction

Intent: Given a language, define its grammar representation, and define an interpreter that uses this representation to interpret sentences in the language.

Main Solution: To build an interpreter for some fixed grammar to interpret sentences.

When to Use: If a specific type of problem occurs frequently enough, it might be worth representing each instance of the problem as a simple language sentence. This way, an interpreter can be built to solve the problem by interpreting these sentences.

How to Solve: Build a syntax tree and define terminal and non-terminal symbols.

Key Code: Build an environment class that contains some global information, usually a HashMap, outside the interpreter.

Application Examples: Compilers, arithmetic expression calculations.

Advantages:

  1. Good scalability and flexibility.
  2. Adds new ways to interpret expressions.
  3. Easy to implement simple grammars.

Disadvantages:

  1. Few applicable scenarios.
  2. Difficult to maintain for complex grammars.
  3. The interpreter pattern can lead to class bloat.
  4. The interpreter pattern uses recursive calls.

Usage Scenarios:

  1. Represent sentences in a language that needs interpretation as an abstract syntax tree.
  2. Use a simple language to express recurring problems.
  3. Scenarios where a simple syntax needs interpretation.

Notes: Few applicable scenarios. In Java, consider using expression4J if applicable.

Implementation

We will create an interface Expression and implement it in concrete classes. Define the TerminalExpression class as the main interpreter in the context. Other classes OrExpression, AndExpression are used to create composite expressions.

InterpreterPatternDemo, our demo class, uses Expression classes to create rules and demonstrate expression parsing.

Step 1

Create an expression interface.

Expression.java

public interface Expression {
   public boolean interpret(String context);
}

Step 2

Create concrete classes implementing the above interface.

TerminalExpression.java

public class TerminalExpression implements Expression {

   private String data;

   public TerminalExpression(String data){
      this.data = data; 
   }

   @Override
   public boolean interpret(String context) {
      if(context.contains(data)){
         return true;
      }
      return false;
   }
}

OrExpression.java

public class OrExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public OrExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) || expr2.interpret(context);
   }
}

AndExpression.java

public class AndExpression implements Expression {

   private Expression expr1 = null;
   private Expression expr2 = null;

   public AndExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) && expr2.interpret(context);
   }
}

Step 3

InterpreterPatternDemo uses Expression classes to create rules and parse them.

InterpreterPatternDemo.java

public class InterpreterPatternDemo {

   // Rule: Robert and John are male
   public static Expression getMaleExpression(){
      Expression robert = new TerminalExpression("Robert");
      Expression john = new TerminalExpression("John");
      return new OrExpression(robert, john);    
   }

   // Rule: Julie is a married woman
   public static Expression getMarriedWomanExpression(){
      Expression julie = new TerminalExpression("Julie");
      Expression married = new TerminalExpression("Married");
      return new AndExpression(julie, married);    
   }

   public static void main(String[] args) {
      Expression isMale = getMaleExpression();
      Expression isMarriedWoman = getMarriedWomanExpression();

      System.out.println("John is male? " + isMale.interpret("John"));
      System.out.println("Julie is a married woman? " 
      + isMarriedWoman.interpret("Married Julie"));
   }
}

Step 4

Execute the program, output results:

John is male? true
Julie is a married woman? true
❮ Composite Entity Pattern Intercepting Filter Pattern ❯