The Interpreter design pattern is a behavioral pattern used to define a grammar for interpreting sentences in a language. It provides a way to evaluate sentences or expressions based on a given set of rules. This pattern is useful when working with languages, expressions, or simple interpreters.
We'll create a simple interpreter that evaluates arithmetic expressions consisting of addition (+
) and numbers.
- Expression Interface - Defines an abstract
interpret()
method. - Number (Terminal Expression) - Represents numbers and directly returns their value.
- Addition (Non-Terminal Expression) - Evaluates the sum of two expressions.
- Main Function - Creates an expression
(5 + 10)
and evaluates it.
This approach can be extended to support more operators and a full expression tree interpreter.
You're developing a robot control system where users can send simple text-based commands like:
MOVE FORWARD 10
TURN LEFT 90
MOVE BACKWARD 5
Instead of hardcoding every possible command, you decide to implement an Interpreter Pattern to parse and execute these commands dynamically.
We are designing a mini command language for our robot, where each command is an expression that gets interpreted and executed. The system will:
- Read commands as strings.
- Convert them into objects (expressions).
- Evaluate and execute them dynamically.
Instead of manually handling each command with if-else statements, we let the Interpreter Pattern handle parsing and execution flexibly.
- Define an abstract
Command
interface – Every robot command follows this interface. - Create concrete command classes – Each command (MOVE, TURN) is implemented as a separate class.
- Use a parser – Converts strings into
Command
objects. - Interpret and execute – Each command executes its logic when interpreted.
Use the Interpreter pattern when:
- You have a simple grammar to interpret – If your problem involves parsing and evaluating structured sentences or expressions (e.g., math expressions, custom scripting languages, or rule engines), the Interpreter pattern is a good fit.
- The grammar is stable and small – This pattern works best when the number of rules in the grammar is relatively limited and does not change often.
- You need a customizable evaluation process – If users or developers need to define new rules or expressions dynamically, this pattern provides flexibility.
- You want an object-oriented approach to parsing – It allows defining expressions as objects and evaluating them using a tree structure.
Avoid the Interpreter pattern when:
- The grammar is too complex – If you have a large set of rules or a complex language (e.g., a full programming language), this pattern becomes inefficient and hard to maintain.
- 🔹 Alternative: Use a parser generator like ANTLR or regular expressions for efficient parsing.
- Performance is critical – Since this pattern represents expressions as objects and builds trees, it consumes more memory and has execution overhead.
- 🔹 Alternative: Convert expressions into bytecode or an Abstract Syntax Tree (AST) and evaluate them efficiently.
- The number of expression types keeps increasing – If you frequently add new grammar rules, the codebase becomes hard to maintain.
- 🔹 Alternative: Use the Visitor Pattern to separate interpretation logic from the structure.
The Interpreter pattern is often used alongside or as an alternative to:
- Composite Pattern – The tree structure used in the Interpreter pattern is similar to the Composite pattern, which treats individual objects and compositions uniformly.
- Visitor Pattern – When interpretation logic becomes too complex, the Visitor pattern helps separate the grammar structure from the logic.
- Flyweight Pattern – To optimize memory usage in case of repeated expressions (e.g., large ASTs), Flyweight can be used to share common subexpressions.
- Builder Pattern – If parsing an input language is required before interpreting, the Builder pattern can help construct expression trees.
Source code examples: Robot Command Interpreter, Math Expression Interpreter