Interpreter is useful only when you truly have a small language or expression grammar to evaluate.
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
What the pattern is trying to do
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
What force creates the need
A system needs to evaluate a small, domain-specific expression language, but scattering parser logic and conditionals would become brittle.
How the pattern responds
Model grammar elements as expression objects and evaluate them through a shared interpret operation.
How the moving parts fit together
Terminal and non-terminal expressions implement a common interface, and composed expression trees evaluate input within a context.
Java example in the Order Management domain
package org.javaomnibus.ecommerce.gof.behavioral;
public interface PromotionRule {
boolean matches(Order order);
}
public final class PremiumCustomerRule implements PromotionRule {
@Override
public boolean matches(Order order) {
return order.isPremiumCustomer();
}
}
public final class AndRule implements PromotionRule {
private final PromotionRule left;
private final PromotionRule right;
public AndRule(PromotionRule left, PromotionRule right) {
this.left = left;
this.right = right;
}
@Override
public boolean matches(Order order) {
return left.matches(order) && right.matches(order);
}
}
Step by step
- Each rule object represents one piece of a small promotion language.
- Composite rules build larger expressions from smaller ones.
- This works when the domain really has reusable grammar-like constructs.
- Interpreter is usually best for narrow DSLs, not for ordinary business logic.
Where this pattern helps
- When you have a small rules language or query DSL
- When the grammar is stable and expression objects improve clarity
When a simpler design is better
- When the logic is ordinary application code without a true language
- When a mature parser or rules engine is more appropriate
What this pattern costs
- Can create many small classes quickly
- Performance and maintainability degrade if the language grows too large
How this fits today
Interpreter is less common in everyday Java, but it remains relevant for rule DSLs, search filters, workflow expressions, and small query languages.
Where teams get it wrong
Forcing normal business branching into interpreter-style classes often overcomplicates code that was never really a language in the first place.