一、模式定义与核心思想
解释器模式是一种行为设计模式,定义了一种语言的文法表示,并创建一个解释器来解释该语言中的句子。它主要用于处理领域特定语言(DSL) 的解析和求值。
核心思想:将语言文法表示为对象结构,通过遍历抽象语法树解释执行
- 将文法规则表示为类层次结构
- 每个文法规则对应一个表达式类
- 通过组合模式构建抽象语法树(AST)
- 遍历AST对表达式进行求值
二、Java代码实现
2.1 基础实现:布尔表达式解释器
java
java
下载
复制
import java.util.Map;
import java.util.HashMap;
import java.util.Stack;
// 1. 抽象表达式接口
public interface BooleanExpression {
boolean interpret(Context context);
// 默认方法:支持And/Or操作符
default BooleanExpression and(BooleanExpression other) {
return new AndExpression(this, other);
}
default BooleanExpression or(BooleanExpression other) {
return new OrExpression(this, other);
}
default BooleanExpression not() {
return new NotExpression(this);
}
}
// 2. 上下文:存储变量值
public class Context {
private Map<String, Boolean> variables = new HashMap<>();
public void setVariable(String name, boolean value) {
variables.put(name, value);
}
public boolean getVariable(String name) {
Boolean value = variables.get(name);
if (value == null) {
throw new IllegalArgumentException("未定义变量: " + name);
}
return value;
}
public boolean hasVariable(String name) {
return variables.containsKey(name);
}
}
// 3. 终结符表达式:变量
public class VariableExpression implements BooleanExpression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
@Override
public boolean interpret(Context context) {
return context.getVariable(name);
}
@Override
public String toString() {
return name;
}
}
// 4. 终结符表达式:常量
public class ConstantExpression implements BooleanExpression {
private boolean value;
public ConstantExpression(boolean value) {
this.value = value;
}
@Override
public boolean interpret(Context context) {
return value;
}
@Override
public String toString() {
return Boolean.toString(value);
}
}
// 5. 非终结符表达式:与操作
public 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(Context context) {
return left.interpret(context) && right.interpret(context);
}
@Override
public String toString() {
return "(" + left + " AND " + right + ")";
}
}
// 6. 非终结符表达式:或操作
public 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(Context context) {
return left.interpret(context) || right.interpret(context);
}
@Override
public String toString() {
return "(" + left + " OR " + right + ")";
}
}
// 7. 非终结符表达式:非操作
public class NotExpression implements BooleanExpression {
private BooleanExpression expression;
public NotExpression(BooleanExpression expression) {
this.expression = expression;
}
@Override
public boolean interpret(Context context) {
return !expression.interpret(context);
}
@Override
public String toString() {
return "NOT " + expression;
}
}
// 8. 文法解析器
public class BooleanExpressionParser {
// 支持的文法规则:
// expression ::= term { ('OR' | '||') term }
// term ::= factor { ('AND' | '&&') factor }
// factor ::= variable | constant | '(' expression ')' | 'NOT' factor
private String[] tokens;
private int pos = 0;
public BooleanExpression parse(String expression) {
// 简单分词
this.tokens = expression.replaceAll("\s+", " ")
.replaceAll("\(", " ( ")
.replaceAll("\)", " ) ")
.trim()
.split("\s+");
this.pos = 0;
return parseExpression();
}
private BooleanExpression parseExpression() {
BooleanExpression expr = parseTerm();
while (pos < tokens.length && (currentTokenIs("OR") || currentTokenIs("||"))) {
consumeToken(); // 消耗OR操作符
BooleanExpression right = parseTerm();
expr = new OrExpression(expr, right);
}
return expr;
}
private BooleanExpression parseTerm() {
BooleanExpression expr = parseFactor();
while (pos < tokens.length && (currentTokenIs("AND") || currentTokenIs("&&"))) {
consumeToken(); // 消耗AND操作符
BooleanExpression right = parseFactor();
expr = new AndExpression(expr, right);
}
return expr;
}
private BooleanExpression parseFactor() {
if (currentTokenIs("(")) {
consumeToken(); // 消耗左括号
BooleanExpression expr = parseExpression();
if (!currentTokenIs(")")) {
throw new RuntimeException("期望右括号");
}
consumeToken(); // 消耗右括号
return expr;
} else if (currentTokenIs("NOT") || currentTokenIs("!")) {
consumeToken(); // 消耗NOT操作符
BooleanExpression expr = parseFactor();
return new NotExpression(expr);
} else if (currentTokenIs("TRUE") || currentTokenIs("FALSE")) {
boolean value = Boolean.parseBoolean(consumeToken());
return new ConstantExpression(value);
} else {
// 假设是变量
String varName = consumeToken();
return new VariableExpression(varName);
}
}
private String currentToken() {
if (pos < tokens.length) {
return tokens[pos];
}
return null;
}
private boolean currentTokenIs(String expected) {
String token = currentToken();
return token != null && token.equals(expected);
}
private String consumeToken() {
if (pos < tokens.length) {
return tokens[pos++];
}
throw new RuntimeException("意外的输入结束");
}
}
// 9. 客户端使用
public class BooleanInterpreterDemo {
public static void main(String[] args) {
// 创建上下文并设置变量值
Context context = new Context();
context.setVariable("A", true);
context.setVariable("B", false);
context.setVariable("C", true);
context.setVariable("D", false);
// 方法1:使用API直接构建表达式
System.out.println("=== 方法1: 直接构建表达式 ===");
BooleanExpression expr1 = new VariableExpression("A")
.and(new VariableExpression("B").or(new VariableExpression("C")))
.and(new NotExpression(new VariableExpression("D")));
System.out.println("表达式: " + expr1);
System.out.println("结果: " + expr1.interpret(context));
// 方法2:使用解析器解析字符串表达式
System.out.println("\n=== 方法2: 解析字符串表达式 ===");
BooleanExpressionParser parser = new BooleanExpressionParser();
String[] expressions = {
"A AND B",
"A OR B",
"A AND (B OR C)",
"NOT A AND (B OR C)",
"(A AND B) OR (C AND D)",
"A AND B AND C AND NOT D",
"TRUE AND (FALSE OR A)"
};
for (String exprStr : expressions) {
try {
BooleanExpression expr = parser.parse(exprStr);
System.out.println("表达式: " + exprStr);
System.out.println("解析为: " + expr);
System.out.println("结果: " + expr.interpret(context));
System.out.println("---");
} catch (Exception e) {
System.out.println("解析失败: " + exprStr + " - " + e.getMessage());
}
}
// 复杂示例
System.out.println("\n=== 复杂示例: 规则引擎 ===");
// 定义业务规则:用户年龄>18 AND (是VIP OR 消费金额>1000) AND NOT 黑名单用户
Context userContext = new Context();
userContext.setVariable("age_over_18", true);
userContext.setVariable("is_vip", false);
userContext.setVariable("purchase_over_1000", true);
userContext.setVariable("is_blacklisted", false);
String rule = "age_over_18 AND (is_vip OR purchase_over_1000) AND NOT is_blacklisted";
BooleanExpression ruleExpr = parser.parse(rule);
System.out.println("规则: " + rule);
System.out.println("解析: " + ruleExpr);
System.out.println("用户是否合格: " + ruleExpr.interpret(userContext));
}
}
2.2 进阶示例:SQL条件表达式解释器
java
java
下载
复制
import java.util.List;
import java.util.ArrayList;
import java.util.function.Predicate;
// 1. SQL表达式接口
public interface SQLExpression<T> {
Predicate<T> interpret();
String toSQL();
}
// 2. 数据库记录泛型上下文
public class DatabaseContext<T> {
private List<T> records = new ArrayList<>();
private Class<T> recordType;
public DatabaseContext(Class<T> recordType) {
this.recordType = recordType;
}
public void addRecord(T record) {
records.add(record);
}
public List<T> query(SQLExpression<T> expression) {
Predicate<T> predicate = expression.interpret();
List<T> result = new ArrayList<>();
for (T record : records) {
if (predicate.test(record)) {
result.add(record);
}
}
return result;
}
}
// 3. 字段表达式
public class FieldExpression<T, R> implements SQLExpression<T> {
private String fieldName;
private ValueExpression<R> value;
private Operator operator;
public enum Operator {
EQ("="), NE("<>"), GT(">"), LT("<"), GE(">="), LE("<="),
LIKE("LIKE"), IN("IN"), NOT_IN("NOT IN");
private final String symbol;
Operator(String symbol) {
this.symbol = symbol;
}
public String getSymbol() {
return symbol;
}
}
public FieldExpression(String fieldName, Operator operator, ValueExpression<R> value) {
this.fieldName = fieldName;
this.operator = operator;
this.value = value;
}
@Override
public Predicate<T> interpret() {
R constValue = value.getValue();
return record -> {
try {
// 通过反射获取字段值
var field = record.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
R fieldValue = (R) field.get(record);
switch (operator) {
case EQ: return fieldValue.equals(constValue);
case NE: return !fieldValue.equals(constValue);
case GT: return ((Comparable)fieldValue).compareTo(constValue) > 0;
case LT: return ((Comparable)fieldValue).compareTo(constValue) < 0;
case GE: return ((Comparable)fieldValue).compareTo(constValue) >= 0;
case LE: return ((Comparable)fieldValue).compareTo(constValue) <= 0;
case LIKE:
if (fieldValue instanceof String && constValue instanceof String) {
String pattern = ((String)constValue).replace("%", ".*");
return ((String)fieldValue).matches(pattern);
}
return false;
default: return false;
}
} catch (Exception e) {
return false;
}
};
}
@Override
public String toSQL() {
return fieldName + " " + operator.getSymbol() + " " + value.toSQL();
}
}
// 4. 值表达式
public class ValueExpression<T> {
private T value;
public ValueExpression(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public String toSQL() {
if (value instanceof String) {
return "'" + value + "'";
} else if (value instanceof Number) {
return value.toString();
} else if (value instanceof Boolean) {
return (Boolean)value ? "TRUE" : "FALSE";
} else {
return value.toString();
}
}
}
// 5. 逻辑表达式
public class AndExpression<T> implements SQLExpression<T> {
private SQLExpression<T> left;
private SQLExpression<T> right;
public AndExpression(SQLExpression<T> left, SQLExpression<T> right) {
this.left = left;
this.right = right;
}
@Override
public Predicate<T> interpret() {
Predicate<T> leftPredicate = left.interpret();
Predicate<T> rightPredicate = right.interpret();
return leftPredicate.and(rightPredicate);
}
@Override
public String toSQL() {
return "(" + left.toSQL() + " AND " + right.toSQL() + ")";
}
}
public class OrExpression<T> implements SQLExpression<T> {
private SQLExpression<T> left;
private SQLExpression<T> right;
public OrExpression(SQLExpression<T> left, SQLExpression<T> right) {
this.left = left;
this.right = right;
}
@Override
public Predicate<T> interpret() {
Predicate<T> leftPredicate = left.interpret();
Predicate<T> rightPredicate = right.interpret();
return leftPredicate.or(rightPredicate);
}
@Override
public String toSQL() {
return "(" + left.toSQL() + " OR " + right.toSQL() + ")";
}
}
public class NotExpression<T> implements SQLExpression<T> {
private SQLExpression<T> expression;
public NotExpression(SQLExpression<T> expression) {
this.expression = expression;
}
@Override
public Predicate<T> interpret() {
Predicate<T> predicate = expression.interpret();
return predicate.negate();
}
@Override
public String toSQL() {
return "NOT " + expression.toSQL();
}
}
// 6. 实体类
public class User {
private int id;
private String name;
private int age;
private boolean active;
private String email;
public User(int id, String name, int age, boolean active, String email) {
this.id = id;
this.name = name;
this.age = age;
this.active = active;
this.email = email;
}
// Getters
public int getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
public boolean isActive() { return active; }
public String getEmail() { return email; }
@Override
public String toString() {
return String.format("User{id=%d, name='%s', age=%d, active=%s, email='%s'}",
id, name, age, active, email);
}
}
// 7. SQL解释器使用示例
public class SQLInterpreterDemo {
public static void main(String[] args) throws Exception {
// 创建数据库上下文
DatabaseContext<User> db = new DatabaseContext<>(User.class);
// 添加测试数据
db.addRecord(new User(1, "张三", 25, true, "zhangsan@example.com"));
db.addRecord(new User(2, "李四", 18, true, "lisi@example.com"));
db.addRecord(new User(3, "王五", 30, false, "wangwu@example.com"));
db.addRecord(new User(4, "赵六", 22, true, "zhaoliu@example.com"));
db.addRecord(new User(5, "孙七", 35, true, "sunqi@example.com"));
// 构建SQL查询表达式
// 查询条件: age >= 20 AND active = true AND (name LIKE '张%' OR email LIKE '%example%')
// 手动构建表达式树
SQLExpression<User> ageCondition = new FieldExpression<>(
"age", FieldExpression.Operator.GE, new ValueExpression<>(20)
);
SQLExpression<User> activeCondition = new FieldExpression<>(
"active", FieldExpression.Operator.EQ, new ValueExpression<>(true)
);
SQLExpression<User> nameCondition = new FieldExpression<>(
"name", FieldExpression.Operator.LIKE, new ValueExpression<>("张%")
);
SQLExpression<User> emailCondition = new FieldExpression<>(
"email", FieldExpression.Operator.LIKE, new ValueExpression<>("%example%")
);
SQLExpression<User> orCondition = new OrExpression<>(nameCondition, emailCondition);
SQLExpression<User> fullCondition = new AndExpression<>(
new AndExpression<>(ageCondition, activeCondition),
orCondition
);
// 执行查询
System.out.println("=== SQL条件查询 ===");
System.out.println("SQL: " + fullCondition.toSQL());
System.out.println("\n查询结果:");
List<User> results = db.query(fullCondition);
for (User user : results) {
System.out.println(user);
}
// 复杂的条件组合
System.out.println("\n=== 复杂条件组合 ===");
// (age > 18 AND age < 30) OR (name = '王五')
SQLExpression<User> ageLower = new FieldExpression<>(
"age", FieldExpression.Operator.GT, new ValueExpression<>(18)
);
SQLExpression<User> ageUpper = new FieldExpression<>(
"age", FieldExpression.Operator.LT, new ValueExpression<>(30)
);
SQLExpression<User> nameEq = new FieldExpression<>(
"name", FieldExpression.Operator.EQ, new ValueExpression<>("王五")
);
SQLExpression<User> ageRange = new AndExpression<>(ageLower, ageUpper);
SQLExpression<User> complexCondition = new OrExpression<>(ageRange, nameEq);
System.out.println("SQL: " + complexCondition.toSQL());
System.out.println("\n查询结果:");
List<User> complexResults = db.query(complexCondition);
for (User user : complexResults) {
System.out.println(user);
}
// 使用流畅API构建表达式
System.out.println("\n=== 流畅API构建 ===");
SQLExpression<User> fluentCondition =
new AndExpression<>(
new FieldExpression<>("age", FieldExpression.Operator.GE, new ValueExpression<>(20)),
new NotExpression<>(
new FieldExpression<>("active", FieldExpression.Operator.EQ, new ValueExpression<>(false))
)
);
System.out.println("SQL: " + fluentCondition.toSQL());
System.out.println("\n查询结果:");
List<User> fluentResults = db.query(fluentCondition);
for (User user : fluentResults) {
System.out.println(user);
}
}
}
三、应用场景
3.1 典型应用场景
-
编程语言编译器/解释器
- 脚本语言解释器
- 正则表达式引擎
- SQL查询解析器
- 模板引擎
-
业务规则引擎
- 风控规则评估
- 促销规则计算
- 工作流条件判断
- 决策表/决策树
-
配置和查询语言
- 日志查询语言(如Log4j的Filter)
- 数据查询语言
- 配置文件解析
- 权限表达式语言
-
数学表达式计算
- 科学计算器
- 公式计算引擎
- 统计表达式
- 金融计算
-
通信协议解析
- 自定义协议解析
- 数据格式转换
- 命令解释器
- 消息路由规则
-
领域特定语言(DSL)
- 游戏脚本语言
- 测试用例描述语言
- 工作流定义语言
- 报表定义语言
3.2 使用时机判断
- ✅ 需要解释执行一种简单的语言
- ✅ 语言的文法比较简单,易于表示
- ✅ 执行效率不是首要考虑因素
- ✅ 语言可能频繁变化或扩展
- ✅ 已有现成的文法表示工具不适用
- ✅ 希望将语言解析与执行逻辑分离
四、优缺点分析
4.1 优点
- 易于扩展文法:新增文法规则只需添加新的表达式类
- 易于实现语言:文法规则的类层次结构清晰
- 支持多种解释:同一语法树可支持不同的解释方式
- 符合开闭原则:新增表达式类型无需修改现有代码
- 简化复杂语法:将复杂语法分解为简单表达式
- 良好的可维护性:每个表达式类职责单一,易于测试
4.2 缺点
- 类数量爆炸:复杂的文法会导致大量类文件
- 执行效率较低:递归调用和对象创建开销大
- 难以维护复杂文法:复杂文法导致类结构复杂
- 不适用于复杂语言:对于复杂编程语言,应使用专业解析器
- 调试困难:解释过程涉及大量递归,调试困难
- 学习曲线陡峭:需要理解文法理论和递归结构
五、模式变体与改进
5.1 模式变体
java
java
下载
复制
// 变体1:带缓存的解释器
public class CachedExpression implements BooleanExpression {
private BooleanExpression expression;
private Map<Context, Boolean> cache = new HashMap<>();
public CachedExpression(BooleanExpression expression) {
this.expression = expression;
}
@Override
public boolean interpret(Context context) {
return cache.computeIfAbsent(context, ctx -> expression.interpret(ctx));
}
}
// 变体2:可变的解释器
public class MutableExpression implements BooleanExpression {
private BooleanExpression expression;
public void setExpression(BooleanExpression expression) {
this.expression = expression;
}
@Override
public boolean interpret(Context context) {
if (expression == null) {
throw new IllegalStateException("表达式未设置");
}
return expression.interpret(context);
}
}
// 变体3:解释器组合器
public class ExpressionCombinator {
public static BooleanExpression and(BooleanExpression... expressions) {
if (expressions.length == 0) return new ConstantExpression(true);
if (expressions.length == 1) return expressions[0];
BooleanExpression result = expressions[0];
for (int i = 1; i < expressions.length; i++) {
result = new AndExpression(result, expressions[i]);
}
return result;
}
public static BooleanExpression or(BooleanExpression... expressions) {
if (expressions.length == 0) return new ConstantExpression(false);
if (expressions.length == 1) return expressions[0];
BooleanExpression result = expressions[0];
for (int i = 1; i < expressions.length; i++) {
result = new OrExpression(result, expressions[i]);
}
return result;
}
}
5.2 结合其他模式
java
java
下载
复制
// 结合访问者模式:遍历语法树
public class ExpressionPrinter implements ExpressionVisitor {
private StringBuilder result = new StringBuilder();
public void visit(VariableExpression expr) {
result.append(expr.getName());
}
public void visit(AndExpression expr) {
result.append("(");
expr.getLeft().accept(this);
result.append(" AND ");
expr.getRight().accept(this);
result.append(")");
}
public String getResult() {
return result.toString();
}
}
// 结合享元模式:共享表达式
public class ExpressionFlyweightFactory {
private Map<String, BooleanExpression> variables = new HashMap<>();
private Map<Boolean, BooleanExpression> constants = new HashMap<>();
public BooleanExpression getVariable(String name) {
return variables.computeIfAbsent(name, VariableExpression::new);
}
public BooleanExpression getConstant(boolean value) {
return constants.computeIfAbsent(value, ConstantExpression::new);
}
}
// 结合建造者模式:流畅API
public class ExpressionBuilder {
private BooleanExpression current;
public ExpressionBuilder variable(String name) {
current = new VariableExpression(name);
return this;
}
public ExpressionBuilder constant(boolean value) {
current = new ConstantExpression(value);
return this;
}
public ExpressionBuilder and(String name) {
current = new AndExpression(current, new VariableExpression(name));
return this;
}
public ExpressionBuilder and(boolean value) {
current = new AndExpression(current, new ConstantExpression(value));
return this;
}
public BooleanExpression build() {
return current;
}
}
六、注意事项与最佳实践
6.1 使用注意事项
-
性能优化
java java 下载 复制 public class OptimizedInterpreter { // 1. 表达式预编译 public static BooleanExpression compile(String expression) { // 解析并优化表达式 BooleanExpression parsed = parse(expression); return optimize(parsed); } // 2. 常量折叠优化 private static BooleanExpression optimize(BooleanExpression expr) { if (expr instanceof AndExpression) { AndExpression and = (AndExpression) expr; BooleanExpression left = optimize(and.getLeft()); BooleanExpression right = optimize(and.getRight()); // 常量折叠: true AND x -> x, false AND x -> false if (left instanceof ConstantExpression) { boolean leftVal = ((ConstantExpression) left).interpret(null); if (!leftVal) return new ConstantExpression(false); if (right instanceof ConstantExpression) { return new ConstantExpression(((ConstantExpression) right).interpret(null)); } return right; } if (right instanceof ConstantExpression) { boolean rightVal = ((ConstantExpression) right).interpret(null); if (!rightVal) return new ConstantExpression(false); return left; } return new AndExpression(left, right); } return expr; } // 3. 解释器缓存 private static class CachedInterpreter { private Map<Context, Map<BooleanExpression, Boolean>> cache = new HashMap<>(); public boolean interpret(Context context, BooleanExpression expr) { return cache.computeIfAbsent(context, k -> new HashMap<>()) .computeIfAbsent(expr, e -> expr.interpret(context)); } } } -
错误处理
java java 下载 复制 public class SafeExpressionParser { public BooleanExpression safeParse(String input) { try { return parse(input); } catch (Exception e) { // 提供友好的错误信息 System.err.println("解析失败: " + input); System.err.println("错误: " + e.getMessage()); // 尝试恢复或返回默认表达式 return new ConstantExpression(false); } } public BooleanExpression parseWithValidation(String input) { BooleanExpression expr = parse(input); validate(expr); return expr; } private void validate(BooleanExpression expr) { // 验证表达式是否有效 Set<String> variables = collectVariables(expr); for (String var : variables) { if (!isValidVariableName(var)) { throw new IllegalArgumentException("无效的变量名: " + var); } } } } -
线程安全
java java 下载 复制 public class ThreadSafeInterpreter { private final Map<Context, Boolean> cache = new ConcurrentHashMap<>(); public boolean interpret(Context context, BooleanExpression expr) { String key = createKey(context, expr); return cache.computeIfAbsent(key, k -> expr.interpret(context)); } private String createKey(Context context, BooleanExpression expr) { return expr.toString() + "@" + System.identityHashCode(context); } }
6.2 最佳实践
-
保持表达式不可变
java java 下载 复制 public final class ImmutableExpression implements BooleanExpression { private final BooleanExpression left; private final BooleanExpression right; public ImmutableExpression(BooleanExpression left, BooleanExpression right) { this.left = left; this.right = right; } // 不提供setter方法 } -
支持表达式序列化
java java 下载 复制 public interface SerializableExpression extends BooleanExpression, Serializable { // 标记接口,支持表达式序列化 } public class SerializableAndExpression implements SerializableExpression { private final SerializableExpression left; private final SerializableExpression right; // 序列化支持 private static final long serialVersionUID = 1L; } -
提供表达式遍历支持
java java 下载 复制 public interface TraversableExpression extends BooleanExpression { void accept(ExpressionVisitor visitor); List<BooleanExpression> getChildren(); } public class ExpressionUtils { public static List<String> collectVariables(BooleanExpression expr) { List<String> variables = new ArrayList<>(); collectVariables(expr, variables); return variables; } private static void collectVariables(BooleanExpression expr, List<String> variables) { if (expr instanceof VariableExpression) { variables.add(((VariableExpression) expr).getName()); } else if (expr instanceof BinaryExpression) { BinaryExpression binary = (BinaryExpression) expr; collectVariables(binary.getLeft(), variables); collectVariables(binary.getRight(), variables); } else if (expr instanceof NotExpression) { collectVariables(((NotExpression) expr).getExpression(), variables); } } } -
实现表达式化简
java java 下载 复制 public class ExpressionSimplifier { public static BooleanExpression simplify(BooleanExpression expr) { if (expr instanceof AndExpression) { AndExpression and = (AndExpression) expr; BooleanExpression left = simplify(and.getLeft()); BooleanExpression right = simplify(and.getRight()); // 恒等律: A AND true = A if (isConstantTrue(right)) return left; if (isConstantTrue(left)) return right; // 零律: A AND false = false if (isConstantFalse(left) || isConstantFalse(right)) { return new ConstantExpression(false); } // 幂等律: A AND A = A if (left.equals(right)) return left; return new AndExpression(left, right); } return expr; } }
七、替代方案与相关模式
-
访问者模式
- 区别:访问者模式分离算法与结构,解释器模式实现语言文法
- 选择:处理已有数据结构用访问者,处理自定义语言用解释器
-
组合模式
- 关系:解释器模式通常使用组合模式构建语法树
- 区别:组合模式关注部分-整体结构,解释器关注语言解释
-
策略模式
- 区别:策略模式封装算法,解释器模式封装文法规则
- 选择:算法选择用策略,语言解释用解释器
-
模板方法模式
- 区别:模板方法定义算法骨架,解释器定义语言文法
- 选择:算法步骤固定用模板方法,语言解释用解释器
-
使用现有解析器生成工具
- ANTLR, JavaCC, Bison, Yacc
- 对于复杂语言,使用这些工具比手写解释器更高效
- 选择标准:语言复杂度、性能要求、开发时间
-
使用脚本语言引擎
- JavaScript引擎(Nashorn, GraalVM)
- Python引擎(Jython)
- Lua引擎(Luaj)
- 当需要完整编程语言功能时,嵌入现有引擎更合适
八、实际应用建议
8.1 何时使用解释器模式
- 实现简单领域特定语言(DSL)
- 需要可配置的业务规则
- 实现查询或过滤语言
- 构建表达式计算器
- 实现模板引擎或脚本语言
8.2 何时避免解释器模式
- 语言文法非常复杂
- 对性能要求极高
- 已有成熟的解析器生成工具
- 只需要简单字符串处理
- 语言频繁变化且结构不稳定
8.3 性能优化建议
- 预编译表达式:解析一次,多次执行
- 缓存解释结果:相同输入缓存结果
- 使用字节码生成:将表达式编译为字节码
- 优化数据结构:使用数组而非链表存储语法树
- 使用栈机:将语法树转换为字节码,用栈机执行
8.4 可扩展性设计
- 插件化文法:支持动态添加文法规则
- 多种后端:支持解释执行和编译执行
- 语法高亮:为表达式提供语法高亮支持
- 调试支持:提供单步执行和断点功能
- 性能分析:收集表达式执行统计信息
九、现代替代方案
java
java
下载
复制
// 使用函数式接口和Lambda
public class FunctionalInterpreter {
@FunctionalInterface
public interface Expression {
boolean evaluate(Context context);
}
public static Expression parseFunctional(String expr) {
// 使用Lambda表达式构建
Context context = new Context();
return ctx -> {
// 动态编译和执行
// 实际实现可使用动态编译或解释执行
return evaluateExpression(expr, ctx);
};
}
// 使用Java动态编译
public static Expression compileToJava(String expr) throws Exception {
String className = "DynamicExpression";
String source = "public class " + className + " implements java.util.function.Predicate<Context> {" +
" public boolean test(Context ctx) {" +
" return " + expr + ";" +
" }" +
"}";
// 使用JavaCompiler动态编译
// 返回编译后的Predicate
return null;
}
}
// 使用现有表达式引擎
public class ExistingEngineExample {
public static void main(String[] args) throws Exception {
// 1. Spring Expression Language (SpEL)
// ExpressionParser parser = new SpelExpressionParser();
// Expression exp = parser.parseExpression("name == '张三' && age > 18");
// 2. MVEL
// Map<String, Object> vars = new HashMap<>();
// vars.put("name", "张三");
// vars.put("age", 20);
// Boolean result = (Boolean) MVEL.eval("name == '张三' && age > 18", vars);
// 3. OGNL
// Object value = Ognl.getValue("name", context);
// 4. JEXL
// JexlEngine jexl = new JexlBuilder().create();
// JexlExpression e = jexl.createExpression("x + y * z");
}
}
总结
解释器模式是实现领域特定语言的经典模式,特别适用于需要解释执行简单语言的场景。它将文法规则表示为对象结构,通过组合模式构建抽象语法树,然后遍历语法树进行求值。
关键价值:在需要灵活、可扩展的语言处理能力,且文法相对简单的场景中,解释器模式提供了一种清晰、面向对象的解决方案。它使得语言扩展变得容易,符合开闭原则,但需注意避免过度设计。
重要权衡:
- 对于简单文法,解释器模式简洁优雅
- 对于复杂文法,应使用专业解析器生成工具
- 在性能敏感场景,考虑预编译或使用现有引擎
- 在可维护性和性能之间找到平衡点
在实际应用中,应根据具体需求评估是否需要实现完整的解释器。对于许多场景,使用现有表达式引擎(如SpEL、MVEL等)可能是更高效的选择。但当需要完全控制语言特性、有特定优化需求或学习目的时,实现自定义解释器仍然是合理的选择。