在开发过程中,有些系统的核心在于对“规则”或“表达式”进行解释和执行。比如:
- 一个自定义的条件表达式语言
- 简单脚本引擎
- SQL、正则、数学公式解析
- 行为系统中的规则判断
这类需求的特点是:规则是可配置的、结构是可以被语法化表示的、系统需要“理解”这些表达式并做出相应行为。
这时候就可以考虑使用 解释器模式 来实现一个可扩展、可维护的语法解析方案。
什么是解释器模式?
解释器模式是一种行为型设计模式,它为语言中的每一个语法规则定义一个类,并通过组合这些类来构建一个解释器,用来解释语法表达式。
通俗理解就是:把“语言”拆解成语法结构,每种语法结构都有对应的类可以解释执行。最终系统可以理解我们自定义的表达式或规则。
模式结构
解释器模式通常包含以下几个核心角色:
- AbstractExpression(抽象表达式):定义解释操作的接口。
- TerminalExpression(终结符表达式):实现与文法中的终结符相关的解释操作。
- NonTerminalExpression(非终结符表达式):实现文法中与非终结符相关的解释操作,通常是递归组合结构。
- Context(上下文):包含解释器需要的全局信息,比如变量值、环境参数等。
示例:简单布尔表达式解释器
为了便于理解,我们实现一个支持 AND、OR 和 变量 的布尔表达式解释器,用户可以定义表达式结构,然后输入一个上下文,系统判断表达式是否为 true。
例如表达式:
A AND (B OR C)
输入上下文为:
A=true, B=false, C=true
结果为 true。
抽象表达式接口
public interface Expression {
boolean interpret(Map<String, Boolean> context);
}
变量表达式(终结符)
public class VariableExpression implements Expression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
@Override
public boolean interpret(Map<String, Boolean> context) {
return context.get(name);
}
}
AND 表达式(非终结符)
public class AndExpression implements Expression {
private Expression left;
private Expression right;
public AndExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(Map<String, Boolean> context) {
return left.interpret(context) && right.interpret(context);
}
}
OR 表达式(非终结符)
public class OrExpression implements Expression {
private Expression left;
private Expression right;
public OrExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public boolean interpret(Map<String, Boolean> context) {
return left.interpret(context) || right.interpret(context);
}
}
客户端使用
public class Main {
public static void main(String[] args) {
// 构造表达式 A AND (B OR C)
Expression A = new VariableExpression("A");
Expression B = new VariableExpression("B");
Expression C = new VariableExpression("C");
Expression orExpr = new OrExpression(B, C);
Expression andExpr = new AndExpression(A, orExpr);
// 构造上下文:A=true, B=false, C=true
Map<String, Boolean> context = new HashMap<>();
context.put("A", true);
context.put("B", false);
context.put("C", true);
boolean result = andExpr.interpret(context);
System.out.println("表达式结果:" + result);
}
}
输出结果:
表达式结果:true
整个过程其实就是用对象树来表示一个语法树,然后通过 interpret 方法不断递归地解释执行。
小结
解释器模式适合用在“语言解释器”、“表达式计算器”这类系统中,把语法结构拆解成对象,组合执行,结构清晰、扩展性强。它的优势在于规则可复用,逻辑独立,符合开闭原则。
不过解释器模式也有个致命的缺点:类爆炸。如果语法结构太复杂,表达式种类太多,会导致类数量迅速上升,维护成本变高。这也是为什么解释器模式更多用于语法简单、自定义语言需求较轻的场景。
适用场景
- 自定义表达式或规则解析引擎
- 配置驱动的逻辑判断系统
- 行为系统中的条件表达式
- 模拟 SQL、正则表达式等语言解释器