解释器模式是一种行为型设计模式,其核心思想是定义一种语言的 “语法规则”,并构建一个 “解释器” 来解释这种语言中的 “句子”(即符合语法规则的表达式)。该模式通过将复杂的语法拆解为多个简单的 “语法单元”(终结符 / 非终结符),用对象表示每个语法单元的解释逻辑,最终递归或迭代地解析整个表达式。

解释器模式的本质是 “用对象表示语法,用解释器执行语法”,适用于需要处理自定义语言、表达式解析或规则验证的场景(如数学表达式计算、配置文件语法解析、正则表达式引擎等)。

image.png
下面我将用 Java 代码实现解释器模式,以简单整数运算表达式解析为例,支持变量、数字以及加法和乘法运算。

  1. AbstractExpression(抽象表达式)

    • 定义了所有表达式的统一接口,声明了 interpret () 方法
    • 是所有终结符和非终结符表达式的父类
1
2
3
4
5
// 抽象表达式
public abstract class AbstractExpression {
public abstract int interpret(Context context);
}

  1. 终结符表达式

    • NumberExpression:处理数字常量,解释时直接返回其值
    • VariableExpression:处理变量,解释时从上下文获取变量值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 数字表达式(终结符)
public class NumberExpression extends AbstractExpression {
private int number;

public NumberExpression(int number) {
this.number = number;
}

@Override
public int interpret(Context context) {
// 数字直接返回其值,不依赖上下文
return number;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 变量表达式(终结符)
public class VariableExpression extends AbstractExpression {
private String variableName;

public VariableExpression(String variableName) {
this.variableName = variableName;
}

@Override
public int interpret(Context context) {
// 从上下文中获取变量值
return context.getVariable(variableName);
}
}


  1. 非终结符表达式

    • AddExpression:处理加法运算,包含左右两个子表达式
    • MultiplyExpression:处理乘法运算,包含左右两个子表达式
    • 非终结符表达式通过递归调用子表达式的 interpret () 方法实现计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 加法表达式(非终结符)
public class AddExpression extends AbstractExpression {
private AbstractExpression leftExpr;
private AbstractExpression rightExpr;

public AddExpression(AbstractExpression leftExpr, AbstractExpression rightExpr) {
this.leftExpr = leftExpr;
this.rightExpr = rightExpr;
}

@Override
public int interpret(Context context) {
// 先解释左表达式,再解释右表达式,最后相加
return leftExpr.interpret(context) + rightExpr.interpret(context);
}
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 乘法表达式(非终结符)
public class MultiplyExpression extends AbstractExpression {
private AbstractExpression leftExpr;
private AbstractExpression rightExpr;

public MultiplyExpression(AbstractExpression leftExpr, AbstractExpression rightExpr) {
this.leftExpr = leftExpr;
this.rightExpr = rightExpr;
}

@Override
public int interpret(Context context) {
// 先解释左表达式,再解释右表达式,最后相乘
return leftExpr.interpret(context) * rightExpr.interpret(context);
}
}

  1. Context(上下文)

    • 存储变量名和对应的值,供变量表达式查询使用
    • 提供 putVariable () 和 getVariable () 方法管理变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 上下文类
import java.util.HashMap;
import java.util.Map;

public class Context {
// 存储变量名到值的映射
private Map<String, Integer> variableMap = new HashMap<>();

// 设置变量值
public void putVariable(String varName, int value) {
variableMap.put(varName, value);
}

// 获取变量值
public int getVariable(String varName) {
return variableMap.getOrDefault(varName, 0);
}
}

  1. Client(客户端)

    • 负责构建抽象语法树(AST),将表达式拆分为各个表达式节点
    • 设置上下文变量值并触发解释过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 客户端类
public class Client {
public static void main(String[] args) {
// 创建上下文并设置变量值
Context context = new Context();
context.putVariable("a", 3);
context.putVariable("b", 4);

// 构建语法树:解析表达式 a + 2 * b
AbstractExpression expression = buildExpression();

// 解释表达式并输出结果
int result = expression.interpret(context);
System.out.println("表达式 a + 2 * b 的计算结果: " + result); // 预期结果: 3 + 2*4 = 11
}

// 构建表达式的抽象语法树
private static AbstractExpression buildExpression() {
// 构建变量a
AbstractExpression varA = new VariableExpression("a");

// 构建数字2
AbstractExpression num2 = new NumberExpression(2);

// 构建变量b
AbstractExpression varB = new VariableExpression("b");

// 构建 2 * b 表达式
AbstractExpression multiplyExpr = new MultiplyExpression(num2, varB);

// 构建 a + (2 * b) 表达式
return new AddExpression(varA, multiplyExpr);
}
}

上述代码的执行流程如下:

  1. 客户端创建上下文对象并设置变量值
  2. 客户端构建抽象语法树,将复杂表达式分解为多个简单表达式的组合
  3. 调用根表达式的 interpret () 方法开始解释过程
  4. 解释过程通过递归方式进行:
    • 非终结符表达式先解释其包含的子表达式
    • 再根据自身语义(加法或乘法)处理子表达式的结果
  5. 最终返回整个表达式的解释结果

这种设计模式的优势在于:

  • 可以轻松扩展新的语法规则(如添加减法、除法)
  • 每个表达式的解释逻辑被封装在独立的类中,职责明确
  • 适合处理简单的自定义语言或表达式解析场景
  • 语法树的结构清晰地反映了表达式的语法结构