Behavioral Complexity: High

Interpreter Pattern

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

The Problem

An e-commerce platform needs a flexible discount rule engine where business users can define rules like “10% off orders above $100” without modifying code. Hard-coding each discount rule creates tight coupling and makes the system rigid.

The Solution

The Interpreter pattern defines a mini-language for discount rules (e.g., PERCENT 10 IF TOTAL_ABOVE 100) and builds an AST of expression objects. A parser service translates rule strings into composable expression objects that can be evaluated against any order context.

Structure

  • Abstract Expression (Expression interface) — Declares interpret(context).
  • Terminal ExpressionsPercentDiscountExpression, FlatDiscountExpression.
  • Non-Terminal ExpressionsConditionalExpression, AndExpression.
  • ContextDiscountContext carries order data.
  • ParserDiscountParserService translates rule strings into expression trees.

Implementation

The supported grammar:

Rule FormatExampleMeaning
PERCENT <n>PERCENT 1010% off the total
FLAT <n>FLAT 5$5 off
<rule> IF TOTAL_ABOVE <n>PERCENT 10 IF TOTAL_ABOVE 10010% off if total exceeds $100
<rule> IF ITEMS_ABOVE <n>FLAT 15 IF ITEMS_ABOVE 5$15 off if more than 5 items
<rule> IF CUSTOMER_IS <type>PERCENT 20 IF CUSTOMER_IS vip20% off for VIP customers
<rule> AND <rule>FLAT 5 AND PERCENT 10Both discounts combined
export interface DiscountContext {
  totalAmount: number;
  itemCount: number;
  customerType: string;
}

export interface Expression {
  interpret(context: DiscountContext): number;
}

NestJS Integration

The DiscountParserService is an @Injectable() singleton provider. It is stateless — it parses rule strings into expression trees on each call. The expression objects themselves are plain classes, created dynamically during parsing. This clean separation means the parser can be injected into any service that needs discount evaluation.

When to Use

  • You need to interpret a simple, well-defined language or set of rules.
  • The grammar is stable and doesn’t change frequently.
  • Business users need to define rules without code changes.

When NOT to Use

  • The grammar is complex — consider a proper parser generator instead.
  • Performance is critical and rules are evaluated millions of times — the tree-walking approach adds overhead.