0
点赞
收藏
分享

微信扫一扫

通过百度构建一个智能体

解释器模式(Interpreter Pattern)学习笔记



1. 模式定义

行为型设计模式,给定一个语言,定义其文法的一种表示,并定义一个解释器,用于解释语言中的句子。通过构建语法树来实现特定领域语言的解释执行。

2. 适用场景

✅ 需要解释执行特定领域语言
✅ 文法规则相对稳定且易于扩展
✅ 需要频繁解释简单语法结构
✅ 不追求高效执行效率的场景
✅ 实现SQL解析、正则表达式引擎等

3. 模式结构

4. 核心角色

角色说明
AbstractExpression抽象表达式:声明解释操作的接口
TerminalExpression终结符表达式:实现与文法中的终结符相关的解释操作
NonterminalExpression非终结符表达式:维护包含其他表达式的结构,实现文法规则的组合解释逻辑
Context上下文:包含解释器需要的全局信息
Client客户端:构建语法树并调用解释方法

5. 代码示例

5.1 数学表达式解析器

// 上下文(存储变量值)
class MathContext {
    private Map<String, Integer> variables = new HashMap<>();
    
    public void setVariable(String name, int value) {
        variables.put(name, value);
    }
    
    public int getVariable(String name) {
        return variables.getOrDefault(name, 0);
    }
}

// 抽象表达式
interface MathExpression {
    int interpret(MathContext context);
}

// 终结符表达式 - 数字
class Number implements MathExpression {
    private int number;
    
    public Number(int number) {
        this.number = number;
    }
    
    public int interpret(MathContext context) {
        return number;
    }
}

// 终结符表达式 - 变量
class Variable implements MathExpression {
    private String name;
    
    public Variable(String name) {
        this.name = name;
    }
    
    public int interpret(MathContext context) {
        return context.getVariable(name);
    }
}

// 非终结符表达式 - 加法
class Add implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public Add(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 非终结符表达式 - 减法
class Subtract implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public Subtract(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) - right.interpret(context);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 构建表达式:a + (b - 10)
        MathContext context = new MathContext();
        context.setVariable("a", 20);
        context.setVariable("b", 30);
        
        MathExpression expression = new Add(
            new Variable("a"),
            new Subtract(
                new Variable("b"),
                new Number(10)
            )
        );
        
        int result = expression.interpret(context);
        System.out.println("计算结果: " + result); // 输出:20 + (30-10) = 40
    }
}

6. 模式变种

6.1 支持优先级运算

class Multiply extends BinaryExpression {
    public Multiply(MathExpression left, MathExpression right) {
        super(left, right);
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) * right.interpret(context);
    }
}

class Power extends BinaryExpression {
    public Power(MathExpression left, MathExpression right) {
        super(left, right);
    }
    
    public int interpret(MathContext context) {
        return (int) Math.pow(
            left.interpret(context),
            right.interpret(context)
        );
    }
}

7. 优缺点分析

✔️ 优点

  • 易于扩展新的文法规则
  • 实现语言解释器的标准模式
  • 将语法解析与表达式求值分离
  • 符合单一职责原则

缺点

  • 复杂文法难以维护(类数量爆炸)
  • 执行效率较低(递归调用多)
  • 应用场景有限
  • 难以处理左递归文法

8. 相关模式对比

模式目的关键区别
组合模式树形结构处理解释器通常使用组合模式构建语法树
访问者模式分离数据结构与操作解释器模式侧重语法解析,访问者侧重数据操作
策略模式封装算法族解释器模式处理语言解析,策略处理算法选择

9. 实际应用案例

  • Java正则表达式引擎(Pattern/Matcher)
  • Spring表达式语言(SpEL)
  • SQL解析器实现
  • 金融领域的业务规则引擎
  • 编译器语法分析阶段
  • XML文档解析器
  • 数学公式计算器

10. 最佳实践建议

  1. 使用组合模式构建语法树
abstract class BinaryExpression implements MathExpression {
    protected MathExpression left;
    protected MathExpression right;
    
    public BinaryExpression(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
}
  1. 结合工厂模式创建表达式
class ExpressionFactory {
    public static MathExpression create(String expr) {
        // 解析表达式字符串,构建语法树
        // 示例:解析 "a + b * 3"
        return new Add(
            new Variable("a"),
            new Multiply(
                new Variable("b"),
                new Number(3)
            )
        );
    }
}
  1. 实现上下文缓存优化
class CachedExpression implements MathExpression {
    private MathExpression expression;
    private Map<MathContext, Integer> cache = new WeakHashMap<>();
    
    public CachedExpression(MathExpression expression) {
        this.expression = expression;
    }
    
    public int interpret(MathContext context) {
        return cache.computeIfAbsent(context, 
            ctx -> expression.interpret(ctx));
    }
}
  1. 使用访问者模式实现多种操作
interface ExpressionVisitor {
    void visit(Number number);
    void visit(Variable variable);
    void visit(Add add);
    void visit(Subtract subtract);
}

class PrintVisitor implements ExpressionVisitor {
    public void visit(Number number) {
        System.out.print(number.value);
    }
    
    public void visit(Variable variable) {
        System.out.print(variable.name);
    }
    
    public void visit(Add add) {
        add.left.accept(this);
        System.out.print(" + ");
        add.right.accept(this);
    }
    // 其他visit方法...
}

11. 扩展应用(SQL条件解析)

// 条件表达式接口
interface Condition {
    boolean interpret(Map<String, Object> row);
}

// 等于条件
class Equals implements Condition {
    private String column;
    private Object value;
    
    public Equals(String column, Object value) {
        this.column = column;
        this.value = value;
    }
    
    public boolean interpret(Map<String, Object> row) {
        return value.equals(row.get(column));
    }
}

// AND条件
class And implements Condition {
    private Condition left;
    private Condition right;
    
    public And(Condition left, Condition right) {
        this.left = left;
        this.right = right;
    }
    
    public boolean interpret(Map<String, Object> row) {
        return left.interpret(row) && right.interpret(row);
    }
}

// 使用示例
Condition condition = new And(
    new Equals("status", "active"),
    new Or(
        new Equals("age", 25),
        new GreaterThan("score", 80)
    )
);

Map<String, Object> row = new HashMap<>();
row.put("status", "active");
row.put("age", 26);
row.put("score", 85);

boolean result = condition.interpret(row); // 返回true

通过解释器模式,可以实现灵活的语言解释功能,特别适合需要自定义领域特定语言(DSL)的场景。该模式在规则引擎、查询语言解析和公式计算等领域应用广泛,是处理语法解析问题的经典解决方案。

举报

相关推荐

0 条评论