解释器模式
定义:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表达式来解释语言中的句子。
解释器模式角色介绍
- AbstractExpression:抽象表达式。
- TerminalExpression:终结符表达式,实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结表达式,但有多个实例,对应不同的终结符。
- NonterminalExpression:非终结符表达式,文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
- Context:环境角色。
以计算器为例子,计算器就为环境角色,加减乘除运算符为非终结符表达式,数字为终结符表达式。
代码示例
抽象表达式
public abstract class AbstractExpression {
public abstract int interpret();
}
数字终结符表表达式
//只有一个终结符表达式
public class NumExpression extends AbstractExpression {
private int num;
public NumExpression(int num) {
this.num = num;
}
public int interpret() {
return num;
}
}
具体非终结符表达式
//加法表达式
public class AdditionExpression extends AbstractExpression {
private AbstractExpression exp1;
private AbstractExpression exp2;
public AdditionExpression(AbstractExpression exp1, AbstractExpression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
}
public int interpret() {
return exp1.interpret() + exp2.interpret();
}
}
//减法表达式
public class MinusExpression extends AbstractExpression {
private AbstractExpression exp1;
private AbstractExpression exp2;
public MinusExpression(AbstractExpression exp1, AbstractExpression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
}
public int interpret() {
return exp1.interpret() - exp2.interpret();
}
}
计算器环境类
public class Calculator {
private Stack<AbstractExpression> expStack = new Stack<AbstractExpression>();
private AbstractExpression exp1;
private AbstractExpression exp2;
public int calculate(String expstr) {
//将输入的字符串以空格隔开
String[] elems = expstr.split(" ");
for (int i = 0; i < elems.length; i++) {
if (elems[i].equals("+")) {
exp1 = expStack.pop();
exp2 = new NumExpression(Integer.valueOf(elems[++i]));
//前一个数字表达式和后一个数字表达式放进加号表达式中
expStack.push(new AdditionExpression(exp1, exp2));
} else if (elems[i].equals("-")) {
exp1 = expStack.pop();
exp2 = new NumExpression(Integer.valueOf(elems[++i]));
//前一个数字表达式和后一个数字表达式放进减号表达式中
expStack.push(new MinusExpression(exp1, exp2));
} else {
//如果是数字表达式直接进栈
expStack.push(new NumExpression(Integer.valueOf(elems[i])));
}
}
//取出第一个表达式的结果
return expStack.pop().interpret();
}
}
客户端
Calculator calculator = new Calculator();
System.out.println(calculator.calculate("3 + 4 - 8"));//输出为-1
解释器模式是一种用得比较少的行为型模式,使用场景其实相当广泛,总的概括下来大致有两种,一是如果某个简单的语言需要解释执行而且可以将该语言中的语句表示为一个抽象语法树时可以考虑使用解释器模式;二是在某些特定的领域出现不断重复的问题时,可以将该领域的问题转化为一种语法规则下的语句,然后构建解释器来解释该语句。如果需要新增只需要增加响应的非终结符解释器,并在构建抽象语法树时,使用到新增的解释器对象进行具体的解释即可。