一,解释器模式
解释器模式:
- 给一个语言表达式,定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的表达示;
- 在编译原理中,一个表达式通过词法分析器形成词单元,而后这些词单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树,这些语法分析器和词法分析器都可以看做解释器;
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树,一些重复出现的问题可以用一种简单的语言来表示,一个简单语法需要解释的等场景;
二,原理类图
意图: 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性:
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
三,实例
Context: 环境角色,含有解释器之外的全局信息;
package com.neei.interpreter;
import java.util.Map;
import java.util.Stack;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/17 22:25
* @Description: 游学网
* @throws:
*/
public class Calculator {
private Expression expression;
public Calculator(String expStr) {
Stack<Expression> stack = new Stack<>();
char[] chars = expStr.toCharArray();
Expression left = null;
Expression right = null;
for (int i = 0; i < chars.length; i++) {
switch (chars[i]) {
case '+':
left = stack.pop();
right = new VarExpression(String.valueOf(chars[++i]));
stack.push(new AddExpression(left, right));
break;
case '-':
left = stack.pop();
right = new VarExpression(String.valueOf(chars[++i]));
stack.push(new SubExpression(left, right));
break;
default:
stack.push(new VarExpression(String.valueOf(chars[i])));
}
this.expression = stack.pop();
}
}
public int run(Map<String,Integer> var){
return this.expression.interpreter(var);
}
}
AbstractExpression: 抽象表达式,声明一个抽象的解释操作,这个方法被抽象语法树中所有的节点所共享;
package com.neei.interpreter;
import java.util.Map;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/17 22:16
* @Description: 游学网
* @throws:
*/
public abstract class Expression {
/**
*a+b-c
* @param var key:表达式参数[a,b,c],value:值10,20...
* var={a=10,b=20}
* @return
*/
abstract int interpreter(Map<String, Integer> var);
}
TerminalExpression: 终结符表达式,实现与文法中的终结符相关的解释操作;
package com.neei.interpreter;
import java.util.Map;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/17 22:18
* @Description: 游学网
* @throws:
*/
public class VarExpression extends Expression {
/**
* key=a,key=b....
*/
private String key;
public VarExpression(String key) {
this.key = key;
}
@Override
int interpreter(Map<String, Integer> var) {
return var.get(key);
}
}
NonTerminalExpression: 非终结符表达式,实现与文法中的非终结符相关的解释操作;
package com.neei.interpreter;
import java.util.Map;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/17 22:17
* @Description: 游学网
* @throws:
*/
public class SymbolExpression extends Expression {
protected Expression left;
protected Expression right;
public SymbolExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
int interpreter(Map<String, Integer> var) {
return 0;
}
}
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
@Override
int interpreter(Map<String, Integer> var) {
return left.interpreter(var) + right.interpreter(var);
}
}
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
@Override
int interpreter(Map<String, Integer> var) {
return super.left.interpreter(var)-super.right.interpreter(var);
}
}
四,源码分析
Spring源码中使用的解释器模式,如org.springframework.expression.spel.standard.SpelExpression;