Java案例中的解释器模式怎么写?

wen java案例 2

Java 解释器模式详解

解释器模式(Interpreter Pattern)是一种行为型设计模式,用于定义语言的文法规则,并解释该语言中的句子。

Java案例中的解释器模式怎么写?

核心概念

主要角色:

  • 抽象表达式(AbstractExpression):定义解释操作的接口
  • 终结符表达式(TerminalExpression):实现文法中的终结符操作
  • 非终结符表达式(NonterminalExpression):实现文法中的非终结符操作
  • 上下文(Context):包含解释器需要的全局信息
  • 客户端(Client):构建抽象语法树并调用解释操作

经典案例:算术表达式解释器

实现一个简单的加减法表达式解释器,支持数字和 、 运算符。

步骤1:定义抽象表达式接口

// 抽象表达式接口
interface Expression {
    int interpret(Context context);
}

步骤2:创建终结符表达式(数字)

// 终结符表达式 - 数字
class NumberExpression implements Expression {
    private int number;
    public NumberExpression(int number) {
        this.number = number;
    }
    @Override
    public int interpret(Context context) {
        return number;
    }
}

步骤3:创建非终结符表达式(运算符)

// 非终结符表达式 - 加法
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);
    }
}
// 非终结符表达式 - 减法
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);
    }
}

步骤4:创建上下文类

// 上下文类(此处可扩展存储变量值等)
class Context {
    // 这里可以存储变量值映射等信息
    // Map<String, Integer> variables;
    // 此简单例子中不需要特殊内容
}

步骤5:创建解析器(可选,用于将表达式字符串转为语法树)

// 解析器 - 将表达式字符串解析为语法树
class Parser {
    public static Expression parse(String expression) {
        // 简单解析:支持 "数字 运算符 数字" 格式
        String[] parts = expression.split(" ");
        if (parts.length == 3) {
            Expression left = new NumberExpression(Integer.parseInt(parts[0]));
            Expression right = new NumberExpression(Integer.parseInt(parts[2]));
            switch (parts[1]) {
                case "+":
                    return new AddExpression(left, right);
                case "-":
                    return new SubtractExpression(left, right);
                default:
                    throw new IllegalArgumentException("不支持的运算符: " + parts[1]);
            }
        }
        throw new IllegalArgumentException("无效表达式格式");
    }
}

步骤6:客户端测试

public class InterpreterPatternDemo {
    public static void main(String[] args) {
        Context context = new Context();
        // 方式一:手动构建语法树
        System.out.println("=== 手动构建语法树 ===");
        Expression add = new AddExpression(
            new NumberExpression(10), 
            new NumberExpression(5)
        );
        System.out.println("10 + 5 = " + add.interpret(context));
        Expression subtract = new SubtractExpression(
            new NumberExpression(20), 
            new NumberExpression(8)
        );
        System.out.println("20 - 8 = " + subtract.interpret(context));
        // 复杂表达式: (10 + 5) - (20 - 8)
        Expression complex = new SubtractExpression(
            new AddExpression(
                new NumberExpression(10), 
                new NumberExpression(5)
            ),
            new SubtractExpression(
                new NumberExpression(20), 
                new NumberExpression(8)
            )
        );
        System.out.println("(10 + 5) - (20 - 8) = " + complex.interpret(context));
        // 方式二:使用解析器
        System.out.println("\n=== 使用解析器 ===");
        Expression parsedAdd = Parser.parse("15 + 7");
        System.out.println("15 + 7 = " + parsedAdd.interpret(context));
        Expression parsedSub = Parser.parse("100 - 33");
        System.out.println("100 - 33 = " + parsedSub.interpret(context));
    }
}

运行结果:

=== 手动构建语法树 ===
10 + 5 = 15
20 - 8 = 12
(10 + 5) - (20 - 8) = 3
=== 使用解析器 ===
15 + 7 = 22
100 - 33 = 67

进阶案例:布尔表达式解释器

实现支持 AND、OR、NOT 的布尔表达式解释器。

// 上下文类
class BooleanContext {
    private Map<String, Boolean> variables = new HashMap<>();
    public void setVariable(String name, boolean value) {
        variables.put(name, value);
    }
    public boolean getVariable(String name) {
        return variables.getOrDefault(name, false);
    }
}
// 抽象表达式
interface BooleanExpression {
    boolean interpret(BooleanContext context);
}
// 变量表达式(终结符)
class VariableExpression implements BooleanExpression {
    private String name;
    public VariableExpression(String name) {
        this.name = name;
    }
    @Override
    public boolean interpret(BooleanContext context) {
        return context.getVariable(name);
    }
}
// 常量表达式(终结符)
class ConstantExpression implements BooleanExpression {
    private boolean value;
    public ConstantExpression(boolean value) {
        this.value = value;
    }
    @Override
    public boolean interpret(BooleanContext context) {
        return value;
    }
}
// AND 表达式(非终结符)
class AndExpression implements BooleanExpression {
    private BooleanExpression left;
    private BooleanExpression right;
    public AndExpression(BooleanExpression left, BooleanExpression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean interpret(BooleanContext context) {
        return left.interpret(context) && right.interpret(context);
    }
}
// OR 表达式(非终结符)
class OrExpression implements BooleanExpression {
    private BooleanExpression left;
    private BooleanExpression right;
    public OrExpression(BooleanExpression left, BooleanExpression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean interpret(BooleanContext context) {
        return left.interpret(context) || right.interpret(context);
    }
}
// NOT 表达式(非终结符)
class NotExpression implements BooleanExpression {
    private BooleanExpression expression;
    public NotExpression(BooleanExpression expression) {
        this.expression = expression;
    }
    @Override
    public boolean interpret(BooleanContext context) {
        return !expression.interpret(context);
    }
}
// 测试
public class BooleanInterpreterDemo {
    public static void main(String[] args) {
        BooleanContext context = new BooleanContext();
        context.setVariable("A", true);
        context.setVariable("B", false);
        context.setVariable("C", true);
        // (A AND B) OR (NOT B AND C)
        BooleanExpression expr = new OrExpression(
            new AndExpression(
                new VariableExpression("A"),
                new VariableExpression("B")
            ),
            new AndExpression(
                new NotExpression(new VariableExpression("B")),
                new VariableExpression("C")
            )
        );
        System.out.println("(A AND B) OR (NOT B AND C) where A=true, B=false, C=true");
        System.out.println("Result: " + expr.interpret(context)); // true
    }
}

实际应用场景

  1. SQL 解析器

    将 SQL 语句解析为语法树执行

  2. 正则表达式引擎

    解释正则表达式模式匹配

  3. 数学表达式计算器

    如公式引擎、科学计算器

  4. 配置文件解析

    如 Spring 的 SpEL 表达式

  5. 脚本语言解释器

    小型 DSL(领域特定语言)的实现

优缺点分析

优点:

  • 易于扩展文法(添加新表达式类)
  • 实现了文法分离,易于维护
  • 可以方便地实现复杂表达式

缺点:

  • 对于复杂文法,类层次会变得庞大
  • 执行效率较低(递归调用)
  • 不适合处理非常复杂的语言

最佳实践建议

  1. 使用时机:当需要解释简单语言且语法规则稳定时考虑使用
  2. 组合使用:常与组合模式一起使用构建语法树
  3. 性能优化:可以使用缓存或 Flyweight 模式优化
  4. 简化实现:对于简单场景,可以考虑使用脚本引擎(如 ScriptEngine)替代

解释器模式虽然不常用,但在需要自定义 DSL 或解析特定格式数据时非常有用,理解其原理有助于设计更灵活的架构。

抱歉,评论功能暂时关闭!