请选择 ‘文档’ 后再开始编辑!解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子
场景
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
- 简单的语法需要解释时,如解释一个sql语句
实现
主要的构成角色如下:
- AbstractExpression:抽象解释器,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
- TerminalExpression:终结解释器,实现与文法中的终结符相关联的解释操作。一个句子中的每一个终结符需要该类的一个实例
- NonterminalExpression:非终结解释器,对文法中的规则的解释操作
- Context:环境角色,包含解释器之外的一些全局信息,一般可由HashMap实现
实现波兰表达式的后缀表达式
Expression,抽象表达式类
public interface Expression {
int interpret(Map<String, Expression> variables);
}
TerminalExpression,末端表达式: 数字与变量
public class Number implements Expression {
private int number;
public Number(int number) {
this.number = number;
}
public int interpret(Map<String, Expression> variables) {
return number;
}
}
public class Variable implements Expression {
private String name;
public Variable(String name) {
this.name = name;
}
public int interpret(Map<String, Expression> variables) {
if (null == variables.get(name))
return 0;
return variables.get(name).interpret(variables);
}
}
NonterminalExpression,非末端表达式: + -操作
public class Minus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Minus(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(Map<String, Expression> variables) {
return leftOperand.interpret(variables) - rightOperand.interpret(variables);
}
}
public class Plus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Plus(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(Map<String, Expression> variables) {
return leftOperand.interpret(variables) + rightOperand.interpret(variables);
}
}
环境角色
public class Evaluator implements Expression {
private Expression syntaxTree;
public Evaluator(String expression) {
Stack<Expression> expressionStack = new Stack<Expression>();
for (String token : expression.split(" ")) {
if (token.equals("+")) {
Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
expressionStack.push(subExpression);
} else if (token.equals("-")) {
Expression right = expressionStack.pop();
Expression left = expressionStack.pop();
Expression subExpression = new Minus(left, right);
expressionStack.push(subExpression);
} else
expressionStack.push(new Variable(token));
}
syntaxTree = expressionStack.pop();
}
public int interpret(Map<String, Expression> context) {
return syntaxTree.interpret(context);
}
}
客户端
public class InterpreterExample {
public static void main(final String[] args) {
final String expression = "w x z - +";
final Evaluator sentence = new Evaluator(expression);
final Map<String, Expression> variables = new HashMap<String, Expression>();
variables.put("w", new Number(5));
variables.put("x", new Number(10));
variables.put("z", new Number(42));
final int result = sentence.interpret(variables);
System.out.println(result);
}
}
优点
最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了
缺点
- 解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦
- 对于复杂的文法,构建其抽象语法树会显得异常繁琐
- 一般场景下,很少使用
Android 中的应用
类似解释器模式:PackageParser#parseBaseApkCommon
、PackageParser#parseBaseApplication
解析 activity、receiver、service
等标签
参考
书籍:《设计模式之禅》、《Android源码设计模式》
技术文章:
菜鸟教程-设计模式、
掘金-设计模式之解释器模式