请选择 ‘文档’ 后再开始编辑!解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子

场景

  • 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
  • 简单的语法需要解释时,如解释一个sql语句

实现

主要的构成角色如下:

  • AbstractExpression:抽象解释器,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
  • TerminalExpression:终结解释器,实现与文法中的终结符相关联的解释操作。一个句子中的每一个终结符需要该类的一个实例
  • NonterminalExpression:非终结解释器,对文法中的规则的解释操作
  • Context:环境角色,包含解释器之外的一些全局信息,一般可由HashMap实现

实现波兰表达式的后缀表达式

Expression,抽象表达式类

  1. public interface Expression {
  2. int interpret(Map<String, Expression> variables);
  3. }

TerminalExpression,末端表达式: 数字与变量

  1. public class Number implements Expression {
  2. private int number;
  3. public Number(int number) {
  4. this.number = number;
  5. }
  6. public int interpret(Map<String, Expression> variables) {
  7. return number;
  8. }
  9. }
  10. public class Variable implements Expression {
  11. private String name;
  12. public Variable(String name) {
  13. this.name = name;
  14. }
  15. public int interpret(Map<String, Expression> variables) {
  16. if (null == variables.get(name))
  17. return 0;
  18. return variables.get(name).interpret(variables);
  19. }
  20. }

NonterminalExpression,非末端表达式: + -操作

  1. public class Minus implements Expression {
  2. Expression leftOperand;
  3. Expression rightOperand;
  4. public Minus(Expression left, Expression right) {
  5. leftOperand = left;
  6. rightOperand = right;
  7. }
  8. public int interpret(Map<String, Expression> variables) {
  9. return leftOperand.interpret(variables) - rightOperand.interpret(variables);
  10. }
  11. }
  12. public class Plus implements Expression {
  13. Expression leftOperand;
  14. Expression rightOperand;
  15. public Plus(Expression left, Expression right) {
  16. leftOperand = left;
  17. rightOperand = right;
  18. }
  19. public int interpret(Map<String, Expression> variables) {
  20. return leftOperand.interpret(variables) + rightOperand.interpret(variables);
  21. }
  22. }

环境角色

  1. public class Evaluator implements Expression {
  2. private Expression syntaxTree;
  3. public Evaluator(String expression) {
  4. Stack<Expression> expressionStack = new Stack<Expression>();
  5. for (String token : expression.split(" ")) {
  6. if (token.equals("+")) {
  7. Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
  8. expressionStack.push(subExpression);
  9. } else if (token.equals("-")) {
  10. Expression right = expressionStack.pop();
  11. Expression left = expressionStack.pop();
  12. Expression subExpression = new Minus(left, right);
  13. expressionStack.push(subExpression);
  14. } else
  15. expressionStack.push(new Variable(token));
  16. }
  17. syntaxTree = expressionStack.pop();
  18. }
  19. public int interpret(Map<String, Expression> context) {
  20. return syntaxTree.interpret(context);
  21. }
  22. }

客户端

  1. public class InterpreterExample {
  2. public static void main(final String[] args) {
  3. final String expression = "w x z - +";
  4. final Evaluator sentence = new Evaluator(expression);
  5. final Map<String, Expression> variables = new HashMap<String, Expression>();
  6. variables.put("w", new Number(5));
  7. variables.put("x", new Number(10));
  8. variables.put("z", new Number(42));
  9. final int result = sentence.interpret(variables);
  10. System.out.println(result);
  11. }
  12. }

优点

最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了

缺点

  • 解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦
  • 对于复杂的文法,构建其抽象语法树会显得异常繁琐
  • 一般场景下,很少使用

Android 中的应用

类似解释器模式:
PackageParser#parseBaseApkCommon
PackageParser#parseBaseApplication 解析 activity、receiver、service等标签

参考

书籍:《设计模式之禅》、《Android源码设计模式》

技术文章:
菜鸟教程-设计模式
掘金-设计模式之解释器模式