一、概述

  提供了评估语言的语法或表达式的方式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。  

  意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

  主要解决:对于一些固定文法构建一个解释句子的解释器。

  注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。

1.1、适用场景

   1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。

  2、一些重复出现的问题可以用一种简单的语言来进行表达。

  3、一个简单语法需要解释的场景。

1.2、优缺点  

  优点: 1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。

  缺点: 1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模式采用递归调用方法。

1.3、类图角色及其职责

  

  AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
  TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
  NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
  Context: 环境类。包含解释器之外的一些全局信息。
  Client: 客户类。
  抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。

1.4、演进过程

  背景:现在我们用解释器模式来实现一个基本的加、减、乘、除和求模运算。例如用户输入表达式“3 * 4 / 2 % 4”,输出结果为2。下图为该实例的UML结构图:

    

  抽象语法树

  

抽象表达式:Node

public interface Node {
int interpret();
}

非终结表达式:ValueNode 主要用解释该表达式的值。

public class ValueNode implements Node {
private int value; public ValueNode(int value) {
this.value = value;
} @Override
public int interpret() {
return this.value;
}
}

终结表达式抽象类,由于该终结表达式需要解释多个运算符号,同时用来构建抽象语法树:

public abstract class SymbolNode implements Node {
protected Node left;
protected Node right; public SymbolNode(Node left, Node right) {
this.left = left;
this.right = right;
}
}
MulNode
public class MulNode extends SymbolNode {
public MulNode(Node left, Node right) {
super(left, right);
} @Override
public int interpret() {
return left.interpret() * right.interpret();
}
}

ModNode

public class ModNode extends SymbolNode {
public ModNode(Node left, Node right) {
super(left, right);
} @Override
public int interpret() {
return super.left.interpret() % super.right.interpret();
}
}

DivNode

public class DivNode extends SymbolNode {
public DivNode(Node left, Node right) {
super(left, right);
} @Override
public int interpret() {
return super.left.interpret() / super.right.interpret();
}
}

Calculator

public class Calculator {
private String statement;
private Node node; public void build(String statement) {
Node left = null, right = null;
Stack stack = new Stack(); String[] statementArr = statement.split(" "); for (int i = 0; i < statementArr.length; i++) {
if (statementArr[i].equalsIgnoreCase("*")) {
left = (Node) stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new MulNode(left, right));
} else if (statementArr[i].equalsIgnoreCase("/")) {
left = (Node) stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new DivNode(left, right));
} else if (statementArr[i].equalsIgnoreCase("%")) {
left = (Node) stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new ModNode(left, right));
} else {
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node = (Node) stack.pop();
} public int compute() {
return node.interpret();
}
}

测试

    @Test
public void compute() {
String statement = "3 * 2 * 4 / 6 % 5";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}

输出

3 * 2 * 4 / 6 % 5 = 4

二、扩展

java.util.regex.Pattern正则解释器,相当于是一个语法。

Spring中的解释器

    @Test
public void compute2() {
// java.util.regex.Pattern p=new Pattern();
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
int value = (int) expression.getValue();
System.out.println(value);
}

使用expression4J代替

最新文章

  1. Oracle参数篇
  2. asp.net ListBox 移除操作的思路
  3. JavaScript 简介
  4. Hibernate,JPA注解@EmbeddedId
  5. SenchaTouch介绍和Sencha Architect介绍以及安装
  6. C基础--关于typedef的用法总结
  7. 反向Ajax,第2部分:WebSocket
  8. c - static 变量
  9. discuz 7.2 faq.php sql注入了一些研究
  10. Activity竟然有两个onCreate方法,可别用错了
  11. Linux - 简明Shell编程14 - 操作符(Operator)
  12. WebApi 接口返回值类型详解 ( 转 )
  13. Hadoop HA高可用集群搭建(Hadoop+Zookeeper+HBase)
  14. windows server 2016 x64用MecaCli工具检查raid5磁盘状态
  15. 1.介绍(introduction)
  16. Mysql数据库的加密与解密
  17. hdu 3861 The King’s Problem trajan缩点+二分图匹配
  18. Mybatis返回HashMap时,某个字段值为null时,不会保存key
  19. H5新增语义化标签
  20. webstorm减少内存占用

热门文章

  1. springboot进行热部署项目
  2. 1206 BBS注册
  3. Vue当中的this
  4. 从零实现jQuery的extend
  5. jquery操作按钮修改对应input属性
  6. 多线程编程threading
  7. Codeforces Round #609 (Div. 2) 【A,B,C】
  8. 洛谷 P816 忠诚 题解
  9. postgresql Kill掉正在执行的SQL语句
  10. word写博客