第二十一章:解释器模式
一、模式简介
1)编译原理中:一个算术表达式通过词法分析器形成词法单元,而后这些词法单元通过语法分析器构建语法分析树,最终形成一个抽象的语法分析树。词法分析器和语法分析器都可以看作是解释器
2)解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,使用这个解释器来解释语言中的表达式
3)应用场景:
- 一些重复出现的问题可以用一种简单的语言来表达(正则表达式)
- 一个简单语法需要解释的场景(运算表达式计算)
- 一个需要解释执行的语言中的句子表示为一个抽象语法树(编译器、解释器、机器人)
基本类图:
- Context:含有解释器之外的全局信息
- AbstractExpression:抽象表达式,声明表达式的解释器行为
- TerminalExpression:终结表达式,就是语法分析树上的叶子节点
- NonTerminalExpression:非终结表达式,语法分析树上的非叶子节点
二、实际案例
用户输入一个算术表达式,如:a + b + c。我们需要实现能够解释这个算术表达式的解释器
为什么需要解释器模式,直接在一个方法中实现表达式运算不可以吗?
扩展性真的就那么好?
抽象表达式类
public abstract class Expression {
public abstract int interpreter(HashMap<String, Integer> vars);
}
终结表达式
public class VarExpression extends Expression {
private String key;
public VarExpression(String key) {
this.key = key;
}
@Override
public int interpreter(HashMap<String, Integer> vars) {
return vars.get(this.key);
}
}
非终结表达式
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int interpreter(HashMap<String, Integer> vars) {
return super.left.interpreter(vars) + super.right.interpreter(vars);
}
}
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int interpreter(HashMap<String, Integer> vars) {
return super.left.interpreter(vars) - super.right.interpreter(vars);
}
}
计算器类(生成语法分析树)
public class Caculator {
private Expression expression;
public Caculator(String expStr) {
Stack<Expression> stack = new Stack<>();
Expression left = null;
Expression right = null;
for (int i = 0; i < expStr.length(); i++) {
switch (expStr.charAt(i)) {
case '+':
left = stack.pop();
right = new VarExpression(expStr.valueOf(expStr.charAt(++i)));
stack.push(new AddExpression(left, right));
break;
case '-':
left = stack.pop();
right = new VarExpression(expStr.valueOf(expStr.charAt(++i)));
stack.push(new SubExpression(left, right));
break;
default:
stack.push(new VarExpression(expStr.valueOf(expStr.charAt(i))));
}
}
this.expression = stack.pop();
}
public int run(HashMap<String, Integer> vars) {
return expression.interpreter(vars);
}
}
测试类
public class InterpreterTest {
public static void main(String[] args) {
String expStr = "a + b - c";
Caculator caculator = new Caculator(expStr);
HashMap<String, Integer> vars = new HashMap<>();
vars.put("a", 1);
vars.put("b", 2);
vars.put("c", 3);
System.out.println(caculator.run(vars));
}
}
三、模式总结
优点:扩展性好
缺点:类膨胀、调试复杂