一、简介
Interpreter模式(解释器模式),通常是用来解析一门语言,如sql解析。
架构如下:
- AbstractInterpreter 定义interpret操作
- TerminalInterpreter 终态节点
- NonTerminalInterpreter 非终态节点,内部调用其他的Interpreter
- Context 上下文对象,存放所有Interpreter共享的信息
Interpreter模式和Composite模式相似,最终将构造为一颗语法树。
以算术表达式"+ – 9 8 7"为例:
二、使用Interpreter模式实现计算器
2.1定义Interpreter接口
public interface Interpreter {
double calculate(String expression);
}
2.2 定义终态Interpreter
public class Number implements Interpreter {
private double number;
public Number(double number) {
super();
this.number = number;
}
@Override
public double calculate(String expression) {
return number;
}
}
2.3 定义非终态Interpreter
Add.java
实现加法操作,注意这里组合了其他的Interpreter对象,而不是直接操作数字。
left和right即可能是数字,也可能是其他的操作。
public class Add implements Interpreter {
private Interpreter left;
private Interpreter right;
public Add(Interpreter left, Interpreter right) {
this.left = left;
this.right = right;
}
@Override
public double calculate(String expression) {
return left.calculate(expression) + right.calculate(expression);
}
}
加减乘除类似,不再赘述。
ParserInterpreter.java
解析算术表达式,构造语法树
/**
* 解析器,构造语法树
* @author ljf
*
*/
public class ParserInterpreter implements Interpreter {
@Override
public double calculate(String expression) { //1 * (2 + 3)
StringBuilder number = new StringBuilder();
LinkedList<Interpreter> interpreters = new LinkedList<>();
LinkedList<Character> operators = new LinkedList<>();
for (char ch : expression.toCharArray()) {
if (isOperator(ch)) {
//将之前的数字入栈
if (number.length() > 0) {
interpreters.add(new Number(Double.parseDouble(number.toString())));
number.setLength(0);
}
//组装表达式
while (interpreters.size() >= 2) {
Character lastOp = operators.getLast();
//碰到左括号
if (isOpenParen(lastOp)) {
break;
}
//碰到了运算符,但下一个运算符优先级是否更高?
if (rightOperatorGreater(lastOp, ch)) {
break;
}
Interpreter right = interpreters.removeLast();
Interpreter left = interpreters.removeLast();
Interpreter interpreter = constructExpression(left,
operators.removeLast(), right);
interpreters.addLast(interpreter);
}
if (isCloseParen(ch)) {
//碰到右括号,直接去掉左括号
operators.removeLast();
} else {
//非右括号,直接进栈
operators.addLast(ch);
}
} else {
number.append(ch);
}
}
//最后是数字,如1*2+3
if (number.length() > 0) {
interpreters.add(new Number(Double.parseDouble(number.toString())));
number.setLength(0);
}
//最后一次运算
if (operators.size() > 0) {
Interpreter right = interpreters.removeLast();
Interpreter left = interpreters.removeLast();
Interpreter interpreter = constructExpression(left,
operators.removeLast(), right);
interpreters.addLast(interpreter);
}
//调用组装好的树
return interpreters.pop().calculate(expression);
}
/**
* 右边运算符是否优先级更高
* @param leftOp
* @param rightOp
* @return
*/
private boolean rightOperatorGreater(char leftOp, char rightOp) {
if (rightOp == '*' || rightOp == '/') {
return leftOp == '+' || leftOp == '-';
}
return false;
}
private boolean isOperator(char ch) {
return ch == '-' || ch == '+' || ch == '/' || ch == '*' || ch == '(' || ch ==')';
}
private boolean isOpenParen(char ch) {
return ch == '(';
}
private boolean isCloseParen(char ch) {
return ch == ')';
}
private Interpreter constructExpression(Interpreter left, char op, Interpreter right) {
switch (op) {
case '+' :
return new Add(left, right);
case '-' :
return new Sub(left, right);
case '*' :
return new Plus(left, right);
case '/' :
return new Divide(left, right);
default:
break;
}
return null;
}
}
2.4 Client
public class Client {
public static void main(String[] args) {
ParserInterpreter interpreter = new ParserInterpreter();
double result = interpreter.calculate("20*(3+1)-4*5+3");
System.out.println("计算结果为: " + result);
}
}