解释器模式(Interpreter Pattern)学习笔记
编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793
DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039
1. 模式定义
行为型设计模式,给定一个语言,定义其文法的一种表示,并定义一个解释器,用于解释语言中的句子。通过构建语法树来实现特定领域语言的解释执行。
2. 适用场景
✅ 需要解释执行特定领域语言
✅ 文法规则相对稳定且易于扩展
✅ 需要频繁解释简单语法结构
✅ 不追求高效执行效率的场景
✅ 实现SQL解析、正则表达式引擎等
3. 模式结构
contains <<interface>> AbstractExpression +interpret(context: Context) : Object TerminalExpression +interpret(context: Context) : Object NonterminalExpression -expressions: List +interpret(context: Context) : Object Context -variables: Map +getVariable(name: String) : Object +setVariable(name: String, value: Object) Client +buildExpressionTree() : AbstractExpression
4. 核心角色
角色 | 说明 |
---|---|
AbstractExpression | 抽象表达式:声明解释操作的接口 |
TerminalExpression | 终结符表达式:实现与文法中的终结符相关的解释操作 |
NonterminalExpression | 非终结符表达式:维护包含其他表达式的结构,实现文法规则的组合解释逻辑 |
Context | 上下文:包含解释器需要的全局信息 |
Client | 客户端:构建语法树并调用解释方法 |
5. 代码示例
5.1 数学表达式解析器
java
// 上下文(存储变量值)
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 支持优先级运算
java
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. 最佳实践建议
- 使用组合模式构建语法树:
java
abstract class BinaryExpression implements MathExpression {
protected MathExpression left;
protected MathExpression right;
public BinaryExpression(MathExpression left, MathExpression right) {
this.left = left;
this.right = right;
}
}
- 结合工厂模式创建表达式:
java
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)
)
);
}
}
- 实现上下文缓存优化:
java
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));
}
}
- 使用访问者模式实现多种操作:
java
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条件解析)
java
// 条件表达式接口
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)的场景。该模式在规则引擎、查询语言解析和公式计算等领域应用广泛,是处理语法解析问题的经典解决方案。