解释器模式

简介

定义: 给定一个语言,定义它的文法的一种表示,并定义一个解释器。

使用场景:

  • 数学表达式计算

  • SQL解析

  • 正则表达式

  • 规则引擎

实现要点:

  • 终结符表达式

  • 非终结符表达式

  • 抽象语法树

  • 上下文对象

UML

代码示例

  1. 抽象表达式接口

public interface Expression {
    
    /**
     * 解释表达式
     * @param context 上下文,包含变量的值
     * @return 解释结果
     */
    int interpret(Context context);
    
    /**
     * 获取表达式字符串表示
     */
    String toString();
}
  1. 表达式具体实现

//非终结符表达式
/**
 * @author dcx
 * @description 加法表达式 - 非终结符表达式
 * @create 2025-01-27
 */
public class AddExpression implements Expression {
    
    private Expression left;
    private Expression right;
    
    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + left.toString() + " + " + right.toString() + ")";
    }
}
/**
 * @author dcx
 * @description 减法表达式 - 非终结符表达式
 * @create 2025-01-27
 */
public class SubtractExpression implements Expression {
    
    private Expression left;
    private Expression right;
    
    public SubtractExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Context context) {
        return left.interpret(context) - right.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + left.toString() + " - " + right.toString() + ")";
    }
}
/**
 * @author dcx
 * @description 乘法表达式 - 非终结符表达式
 * @create 2025-01-27
 */
public class MultiplyExpression implements Expression {
    
    private Expression left;
    private Expression right;
    
    public MultiplyExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Context context) {
        return left.interpret(context) * right.interpret(context);
    }
    
    @Override
    public String toString() {
        return "(" + left.toString() + " * " + right.toString() + ")";
    }
}
/**
 * @author dcx
 * @description 除法表达式 - 非终结符表达式
 * @create 2025-01-27
 */
public class DivideExpression implements Expression {
    
    private Expression left;
    private Expression right;
    
    public DivideExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    
    @Override
    public int interpret(Context context) {
        int divisor = right.interpret(context);
        if (divisor == 0) {
            throw new ArithmeticException("除数不能为0");
        }
        return left.interpret(context) / divisor;
    }
    
    @Override
    public String toString() {
        return "(" + left.toString() + " / " + right.toString() + ")";
    }
}
//终结符表达式
/**
 * @author dcx
 * @description 数字表达式 - 终结符表达式
 * @create 2025-01-27
 */
public class NumberExpression implements Expression {
    
    private int number;
    
    public NumberExpression(int number) {
        this.number = number;
    }
    
    @Override
    public int interpret(Context context) {
        return number;
    }
    
    @Override
    public String toString() {
        return String.valueOf(number);
    }
}
/**
 * @author dcx
 * @description 变量表达式 - 终结符表达式
 * @create 2025-01-27
 */
public class VariableExpression implements Expression {
    
    private String name;
    
    public VariableExpression(String name) {
        this.name = name;
    }
    
    @Override
    public int interpret(Context context) {
        return context.getVariable(name);
    }
    
    @Override
    public String toString() {
        return name;
    }
}
  1. 表达式解析器

public class ExpressionParser {
    
    /**
     * 解析表达式字符串
     * 支持格式: "OrderCglibProxy + b", "10 * 5", "x - y + z" 等
     * 使用后缀表达式(逆波兰表达式)解析
     * 
     * @param expression 表达式字符串,如 "OrderCglibProxy + b * c"
     * @return Expression对象
     */
    public static Expression parse(String expression) {
        // 简化版:只支持两个操作数的简单表达式
        String[] tokens = expression.trim().split("\\s+");
        
        if (tokens.length == 1) {
            // 单个数字或变量
            return parseToken(tokens[0]);
        } else if (tokens.length == 3) {
            // 简单二元表达式: "OrderCglibProxy + b"
            Expression left = parseToken(tokens[0]);
            String operator = tokens[1];
            Expression right = parseToken(tokens[2]);
            
            return createBinaryExpression(left, operator, right);
        } else {
            // 复杂表达式,使用栈解析
            return parseComplexExpression(tokens);
        }
    }
    
    /**
     * 解析单个token(数字或变量)
     */
    private static Expression parseToken(String token) {
        try {
            // 尝试解析为数字
            int number = Integer.parseInt(token);
            return new NumberExpression(number);
        } catch (NumberFormatException e) {
            // 解析为变量
            return new VariableExpression(token);
        }
    }
    
    /**
     * 创建二元表达式
     */
    private static Expression createBinaryExpression(Expression left, String operator, Expression right) {
        switch (operator) {
            case "+":
                return new AddExpression(left, right);
            case "-":
                return new SubtractExpression(left, right);
            case "*":
                return new MultiplyExpression(left, right);
            case "/":
                return new DivideExpression(left, right);
            default:
                throw new IllegalArgumentException("不支持的运算符: " + operator);
        }
    }
    
    /**
     * 解析复杂表达式(简化版,使用优先级处理)
     */
    private static Expression parseComplexExpression(String[] tokens) {
        Stack<Expression> stack = new Stack<>();
        Stack<String> operators = new Stack<>();
        
        for (String token : tokens) {
            if (isOperator(token)) {
                // 处理运算符优先级
                while (!operators.isEmpty() && 
                       getPriority(operators.peek()) >= getPriority(token)) {
                    String op = operators.pop();
                    Expression right = stack.pop();
                    Expression left = stack.pop();
                    stack.push(createBinaryExpression(left, op, right));
                }
                operators.push(token);
            } else {
                // 操作数
                stack.push(parseToken(token));
            }
        }
        
        // 处理剩余的运算符
        while (!operators.isEmpty()) {
            String op = operators.pop();
            Expression right = stack.pop();
            Expression left = stack.pop();
            stack.push(createBinaryExpression(left, op, right));
        }
        
        return stack.pop();
    }
    
    /**
     * 判断是否是运算符
     */
    private static boolean isOperator(String token) {
        return token.equals("+") || token.equals("-") || 
               token.equals("*") || token.equals("/");
    }
    
    /**
     * 获取运算符优先级
     */
    private static int getPriority(String operator) {
        switch (operator) {
            case "+":
            case "-":
                return 1;
            case "*":
            case "/":
                return 2;
            default:
                return 0;
        }
    }
}
  1. 上下文,存储变量和值

public class Context {
    
    /**
     * 存储变量的值
     */
    private Map<String, Integer> variables;
    
    public Context() {
        this.variables = new HashMap<>();
    }
    
    /**
     * 设置变量的值
     */
    public void setVariable(String name, int value) {
        variables.put(name, value);
    }
    
    /**
     * 获取变量的值
     */
    public int getVariable(String name) {
        if (!variables.containsKey(name)) {
            throw new IllegalArgumentException("未定义的变量: " + name);
        }
        return variables.get(name);
    }
    
    /**
     * 是否包含变量
     */
    public boolean hasVariable(String name) {
        return variables.containsKey(name);
    }
    
    /**
     * 显示所有变量
     */
    public void showVariables() {
        System.out.println("📊 变量列表:");
        for (Map.Entry<String, Integer> entry : variables.entrySet()) {
            System.out.println("   " + entry.getKey() + " = " + entry.getValue());
        }
    }
}
  1. 使用方式

public class Test {

    public static void main(String[] args) {
        System.out.println("=== 解释器模式 - 数学表达式解释器示例 ===\n");

        // 创建上下文
        Context context = new Context();

        // ========== 场景1:手动构建表达式树 ==========
        System.out.println("【场景1:手动构建表达式树】\n");
        
        // 表达式: (5 + 3) * 2
        Expression exp1 = new MultiplyExpression(
            new AddExpression(
                new NumberExpression(5),
                new NumberExpression(3)
            ),
            new NumberExpression(2)
        );
        
        System.out.println("表达式: " + exp1);
        System.out.println("计算结果: " + exp1.interpret(context));
        System.out.println("验证: (5 + 3) * 2 = 16 ✅");

        // ========== 场景2:使用变量 ==========
        System.out.println("\n\n【场景2:使用变量】\n");
        
        // 设置变量
        context.setVariable("OrderCglibProxy", 10);
        context.setVariable("b", 20);
        context.setVariable("c", 5);
        
        context.showVariables();
        
        // 表达式: OrderCglibProxy + b
        Expression exp2 = new AddExpression(
            new VariableExpression("OrderCglibProxy"),
            new VariableExpression("b")
        );
        
        System.out.println("\n表达式: " + exp2);
        System.out.println("计算结果: " + exp2.interpret(context));
        System.out.println("验证: OrderCglibProxy + b = 10 + 20 = 30 ✅");
        
        // 表达式: (OrderCglibProxy + b) * c
        Expression exp3 = new MultiplyExpression(
            new AddExpression(
                new VariableExpression("OrderCglibProxy"),
                new VariableExpression("b")
            ),
            new VariableExpression("c")
        );
        
        System.out.println("\n表达式: " + exp3);
        System.out.println("计算结果: " + exp3.interpret(context));
        System.out.println("验证: (OrderCglibProxy + b) * c = (10 + 20) * 5 = 150 ✅");

        // ========== 场景3:使用解析器 ==========
        System.out.println("\n\n【场景3:使用解析器解析字符串表达式】\n");
        
        String[] expressions = {
            "10 + 5",
            "20 - 8",
            "6 * 7",
            "100 / 4",
            "OrderCglibProxy + b",
            "OrderCglibProxy * c",
            "10 + 5 * 2"
        };
        
        for (String exprStr : expressions) {
            try {
                Expression expr = ExpressionParser.parse(exprStr);
                int result = expr.interpret(context);
                System.out.println("表达式: " + exprStr + " = " + result);
            } catch (Exception e) {
                System.out.println("表达式: " + exprStr + " - 解析失败: " + e.getMessage());
            }
        }

        // ========== 场景4:复杂表达式 ==========
        System.out.println("\n\n【场景4:复杂表达式】\n");
        
        // (OrderCglibProxy + b) - (c * 2)
        Expression exp4 = new SubtractExpression(
            new AddExpression(
                new VariableExpression("OrderCglibProxy"),
                new VariableExpression("b")
            ),
            new MultiplyExpression(
                new VariableExpression("c"),
                new NumberExpression(2)
            )
        );
        
        System.out.println("表达式: " + exp4);
        System.out.println("计算结果: " + exp4.interpret(context));
        System.out.println("验证: (OrderCglibProxy + b) - (c * 2) = (10 + 20) - (5 * 2) = 20 ✅");

        // ========== 场景5:动态改变变量值 ==========
        System.out.println("\n\n【场景5:动态改变变量值】\n");
        
        Expression exp5 = ExpressionParser.parse("OrderCglibProxy + b");
        
        System.out.println("表达式: " + exp5);
        System.out.println("当 OrderCglibProxy=10, b=20 时,结果: " + exp5.interpret(context));
        
        // 改变变量值
        context.setVariable("OrderCglibProxy", 100);
        context.setVariable("b", 200);
        System.out.println("当 OrderCglibProxy=100, b=200 时,结果: " + exp5.interpret(context));

        // ========== 场景6:错误处理 ==========
        System.out.println("\n\n【场景6:错误处理】\n");
        
        // 除以0
        try {
            Expression exp6 = new DivideExpression(
                new NumberExpression(10),
                new NumberExpression(0)
            );
            System.out.println("表达式: " + exp6);
            exp6.interpret(context);
        } catch (ArithmeticException e) {
            System.out.println("❌ 错误: " + e.getMessage());
        }
        
        // 未定义的变量
        try {
            Expression exp7 = new VariableExpression("x");
            System.out.println("\n表达式: " + exp7);
            exp7.interpret(context);
        } catch (IllegalArgumentException e) {
            System.out.println("❌ 错误: " + e.getMessage());
        }

        // ========== 总结 ==========
        System.out.println("\n\n=== 解释器模式说明 ===");
        System.out.println("1. 抽象表达式: Expression - 定义解释操作");
        System.out.println("2. 终结符表达式: NumberExpression、VariableExpression - 叶子节点");
        System.out.println("3. 非终结符表达式: AddExpression等 - 组合节点");
        System.out.println("4. 上下文: Context - 存储全局信息(变量值)");
        System.out.println("5. 解析器: ExpressionParser - 将字符串转为表达式树");

        System.out.println("\n=== 解释器模式优势 ===");
        System.out.println("✅ 易于扩展: 添加新的解释规则很容易");
        System.out.println("✅ 易于实现: 文法规则直接映射为类");
        System.out.println("✅ 灵活性: 可以动态改变和扩展语法");
        System.out.println("✅ 复用性: 表达式对象可以复用");

        System.out.println("\n=== 解释器模式缺点 ===");
        System.out.println("⚠️ 复杂文法难维护: 类数量会快速增长");
        System.out.println("⚠️ 性能问题: 递归解释可能导致性能问题");
        System.out.println("⚠️ 效率较低: 相比编译型语言效率低");

        System.out.println("\n=== 解释器模式应用场景 ===");
        System.out.println("📌 数学表达式: 计算器、公式解析");
        System.out.println("📌 SQL解析: 数据库查询语言");
        System.out.println("📌 正则表达式: 模式匹配");
        System.out.println("📌 配置文件: 配置语法解析");
        System.out.println("📌 脚本语言: 简单脚本解释器");
        System.out.println("📌 规则引擎: 业务规则解释");

        System.out.println("\n=== 解释器模式关键概念 ===");
        System.out.println("🔑 文法规则: 定义语言的语法");
        System.out.println("🔑 抽象语法树: 用树结构表示表达式");
        System.out.println("🔑 终结符: 语法的最小单位(数字、变量)");
        System.out.println("🔑 非终结符: 由其他符号组成(加法、乘法)");
        System.out.println("🔑 上下文: 存储解释过程中的全局信息");

        System.out.println("\n=== Java中的解释器模式应用 ===");
        System.out.println("🔸 java.util.regex.Pattern: 正则表达式");
        System.out.println("🔸 javax.el.ELContext: EL表达式");
        System.out.println("🔸 SpEL: Spring表达式语言");
        System.out.println("🔸 OGNL: 对象导航图语言");
        System.out.println("🔸 SQL解析器: MyBatis、Hibernate等");

        System.out.println("\n=== 何时不应使用解释器模式 ===");
        System.out.println("❌ 复杂的语法: 应使用编译器工具(ANTLR、JavaCC)");
        System.out.println("❌ 性能要求高: 应使用编译型方案");
        System.out.println("❌ 频繁变化的文法: 维护成本太高");
    }
}

Last updated

Was this helpful?