Skip to content

解释器

更新: 6/28/2025 字数: 0 字 时长: 0 分钟

定义

解释器模式 (Interpreter Pattern) 给定一个语言,定义它的文法表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。它主要用于需要解释执行的语言,如正则表达式、SQL 解析等。

角色

  • 抽象表达式 (Abstract Expression):声明解释操作的接口
  • 终结符表达式 (Terminal Expression):实现文法中终结符的解释
  • 非终结符表达式 (Nonterminal Expression):实现文法规则的解释
  • 上下文 (Context):包含解释器之外的信息
  • 客户端 (Client):构建语法树并调用解释操作

实现

布尔表达式解释器

java
// 抽象表达式
public interface Expression {
    boolean interpret(String context);
}

// 终结符表达式
public class TerminalExpression implements Expression {
    private String data;
    
    public TerminalExpression(String data) {
        this.data = data;
    }
    
    @Override
    public boolean interpret(String context) {
        return context.contains(data);
    }
}

// 非终结符表达式:AND
public class AndExpression implements Expression {
    private Expression expr1;
    private Expression expr2;
    
    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);
    }
}

// 非终结符表达式:OR
public class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;
    
    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);
    }
}

// 非终结符表达式:NOT
public class NotExpression implements Expression {
    private Expression expr;
    
    public NotExpression(Expression expr) {
        this.expr = expr;
    }
    
    @Override
    public boolean interpret(String context) {
        return !expr.interpret(context);
    }
}

// 客户端使用
public class InterpreterDemo {
    // 规则:Robert 和 John 是男性
    public static Expression getMaleExpression() {
        Expression robert = new TerminalExpression("Robert");
        Expression john = new TerminalExpression("John");
        return new OrExpression(robert, john);
    }
    
    // 规则:Julie 是已婚女性
    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"));
    }
}

数学表达式解释器

java
// 抽象表达式
public interface MathExpression {
    int interpret(Map<String, Integer> context);
}

// 变量表达式
public class VariableExpression implements MathExpression {
    private String name;
    
    public VariableExpression(String name) {
        this.name = name;
    }
    
    @Override
    public int interpret(Map<String, Integer> context) {
        return context.getOrDefault(name, 0);
    }
}

// 数字表达式
public class NumberExpression implements MathExpression {
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    @Override
    public int interpret(Map<String, Integer> context) {
        return number;
    }
}

// 加法表达式
public class AddExpression implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public AddExpression(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 减法表达式
public class SubtractExpression implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public SubtractExpression(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) - right.interpret(context);
    }
}

// 乘法表达式
public class MultiplyExpression implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public MultiplyExpression(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) * right.interpret(context);
    }
}

// 客户端使用
public class MathInterpreterDemo {
    public static void main(String[] args) {
        // 创建表达式:a + b * c
        MathExpression a = new VariableExpression("a");
        MathExpression b = new VariableExpression("b");
        MathExpression c = new VariableExpression("c");
        MathExpression expr = new AddExpression(
            a,
            new MultiplyExpression(b, c)
        );
        
        // 设置上下文
        Map<String, Integer> context = new HashMap<>();
        context.put("a", 10);
        context.put("b", 5);
        context.put("c", 2);
        
        // 解释执行
        int result = expr.interpret(context);
        System.out.println("结果:" + result); // 输出:20
    }
}

优缺点

优点:

  1. 易于扩展文法
  2. 实现文法简单直接
  3. 适合领域特定语言 (DSL)
  4. 符合单一职责原则
  5. 可与其他模式结合使用

缺点:

  1. 复杂文法难以维护
  2. 执行效率较低
  3. 类数量可能爆炸
  4. 难以处理复杂语法
  5. 不易调试

应用场景

  1. 正则表达式引擎
  2. SQL 解析器
  3. 编译器实现
  4. 规则引擎系统
  5. 数学公式计算
  6. 配置文件解析
  7. 机器人指令解释

与其他模式的关系

  • 与组合模式:抽象语法树是组合模式的应用
  • 与访问者模式:可用于遍历抽象语法树
  • 与享元模式:共享终结符表达式
  • 与迭代器模式:遍历表达式结构
  • 与备忘录模式:保存解释状态

JDK 中的解释器模式

  1. Java 正则表达式(Pattern, Matcher)
  2. Java EL 表达式(javax.el)
  3. Java 编译器 API(javax.tools)
  4. Spring 表达式语言(SpEL)
  5. XML 解析器(DOM, SAX)
  6. Java 注解处理器

注意事项

  1. 避免复杂文法(维护困难)
  2. 考虑性能优化(缓存解释结果)
  3. 设计合理的抽象语法树
  4. 处理错误和异常情况
  5. 支持扩展语法
  6. 使用其他模式辅助实现
  7. 考虑内存管理(表达式对象)

贡献者

The avatar of contributor named as AKAcxp AKAcxp

页面历史