# 这个无敌设计，可以解析并运算任意数学表达式

## 1　使用解释器模式解析数学表达式

``````
public interface IArithmeticInterpreter {
int interpret();
}
``````

``````
public abstract class Interpreter implements IArithmeticInterpreter {

protected IArithmeticInterpreter left;
protected IArithmeticInterpreter right;

public Interpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
this.left = left;
this.right = right;
}
}
``````

``````
public class AddInterpreter extends Interpreter {

public AddInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
super(left, right);
}

public int interpret() {
return this.left.interpret() + this.right.interpret();
}
}
``````

``````
public class SubInterpreter extends Interpreter {
public SubInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right) {
super(left, right);
}

public int interpret() {
return this.left.interpret() - this.right.interpret();
}
}
``````

``````
public class MultiInterpreter extends Interpreter {

public MultiInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
super(left,right);
}

public int interpret() {
return this.left.interpret() * this.right.interpret();
}

}
``````

``````
public class DivInterpreter extends Interpreter {

public DivInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter right){
super(left,right);
}

public int interpret() {
return this.left.interpret() / this.right.interpret();
}

}
``````

``````
public class NumInterpreter implements IArithmeticInterpreter {
private int value;

public NumInterpreter(int value) {
this.value = value;
}

public int interpret() {
return this.value;
}
}
``````

``````
public class GPCalculator {
private Stack stack = new Stack();

public GPCalculator(String expression) {
this.parse(expression);
}

private void parse(String expression) {
String [] elements = expression.split(" ");
IArithmeticInterpreter left,right;

for (int i = 0; i < elements.length ; i++) {
String operator = elements[i];
if(OperatorUtil.ifOperator(operator)){
left = this.stack.pop();
right = new NumInterpreter(Integer.valueOf(elements[++i]));
System.out.println("出栈" + left.interpret() + "和" + right.interpret());
this.stack.push(OperatorUtil.getInterpreter(left,right,operator));
System.out.println("应用运算符：" + operator);
}else {
NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements[i]));
this.stack.push(numInterpreter);
System.out.println("入栈：" + numInterpreter.interpret());
}

}
}

public int calculate() {
return this.stack.pop().interpret();
}
}
``````

``````
public class OperatorUtil {

public static boolean isOperator(String symbol) {
return (symbol.equals("+") || symbol.equals("-") || symbol.equals("*"));
}

public static Interpreter getInterpreter(IArithmeticInterpreter left, IArithmeticInterpreter
right, String symbol) {
if (symbol.equals("+")) {
} else if (symbol.equals("-")) {
return new SubInterpreter(left, right);
} else if (symbol.equals("*")) {
return new MultiInterpreter(left, right);
} else if (symbol.equals("/")) {
return new DivInterpreter(left, right);
}
return null;
}
}
``````

``````
public static void main(String[] args) {
System.out.println("result: " + new GPCalculator("10 + 30").calculate());
System.out.println("result: " + new GPCalculator("10 + 30 - 20").calculate());
System.out.println("result: " + new GPCalculator("100 * 2 + 400 * 1 + 66").calculate());
}
``````

``````
public enum OperatorEnum {
LEFT_BRACKET("("),
RIGHT_BRACKET(")"),
SUB("-"),
MULTI("*"),
DIV("/"),
;
private String operator;

public String getOperator() {
return operator;
}

OperatorEnum(String operator) {
this.operator = operator;
}
}
``````

``````
public class OperatorUtil {

public static Interpreter getInterpreter(Stack numStack, Stack operatorStack) {
IArithmeticInterpreter right = numStack.pop();
IArithmeticInterpreter left = numStack.pop();
String symbol = operatorStack.pop();
System.out.println("数字出栈：" + right.interpret() + "," + left.interpret() + ",操作符出栈:" + symbol);
if (symbol.equals("+")) {
} else if (symbol.equals("-")) {
return new SubInterpreter(left, right);
} else if (symbol.equals("*")) {
return new MultiInterpreter(left, right);
} else if (symbol.equals("/")) {
return new DivInterpreter(left, right);
}
return null;
}
}
``````

``````
public class GPCalculator {

//数字stack
private Stack numStack = new Stack();
//操作符stack
private Stack operatorStack = new Stack();
/**
* 解析表达式
* @param expression
*/
public GPCalculator(String expression) {
this.parse(expression);
}

private void parse(String input) {
//对表达式去除空字符操作
String expression = this.fromat(input);
System.out.println("标准表达式：" + expression);
for (String s : expression.split(" ")) {
if (s.length() == 0){
//如果是空格，则继续循环，什么也不操作
continue;
}
//如果是加减，因为加减的优先级最低，所以这里只要遇到加减号，无论操作符栈中是什么运算符都要运算
|| s.equals(OperatorEnum.SUB.getOperator())) {
//当栈不是空的，并且栈中最上面的一个元素是加减乘除的任意一个
while (!operatorStack.isEmpty()
&&(operatorStack.peek().equals(OperatorEnum.SUB.getOperator())
|| operatorStack.peek().equals(OperatorEnum.MULTI.getOperator())
|| operatorStack.peek().equals(OperatorEnum.DIV.getOperator()))) {
//结果存入栈中
numStack.push(OperatorUtil.getInterpreter(numStack,operatorStack));
}
//运算完后将当前的运算符入栈
System.out.println("操作符入栈:"+s);
operatorStack.push(s);
}
//当前运算符是乘除的时候，因为优先级高于加减
//所以要判断最上面的是否是乘除，如果是乘除，则运算，否则直接入栈
else if (s.equals(OperatorEnum.MULTI.getOperator())
|| s.equals(OperatorEnum.DIV.getOperator())) {
while (!operatorStack.isEmpty()&&(
operatorStack.peek().equals(OperatorEnum.MULTI.getOperator())
|| operatorStack.peek().equals(OperatorEnum.DIV.getOperator()))) {
numStack.push(OperatorUtil.getInterpreter(numStack,operatorStack));
}
//将当前操作符入栈
System.out.println("操作符入栈:"+s);
operatorStack.push(s);
}
//如果是左括号，则直接入栈，什么也不用操作，trim()函数是用来去除空格的，由于上面的分割                 操作，可能会令操作符带有空格
else if (s.equals(OperatorEnum.LEFT_BRACKET.getOperator())) {
System.out.println("操作符入栈:"+s);
operatorStack.push(OperatorEnum.LEFT_BRACKET.getOperator());
}
//如果是右括号，则清除栈中的运算符直至左括号
else if (s.equals(OperatorEnum.RIGHT_BRACKET.getOperator())) {
while (!OperatorEnum.LEFT_BRACKET.getOperator().equals(operatorStack.peek())) {
//开始运算
numStack.push(OperatorUtil.getInterpreter(numStack,operatorStack));
}
//运算完之后清除左括号
String pop = operatorStack.pop();
System.out.println("括号运算操作完成，清除栈中右括号："+pop);
}
//如果是数字，则直接入数据的栈
else {
//将数字字符串转换成数字，然后存入栈中
NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(s));
System.out.println("数字入栈："+s);
numStack.push(numInterpreter);
}
}
//最后当栈中不是空的时候继续运算，直到栈为空即可
while (!operatorStack.isEmpty()) {
numStack.push(OperatorUtil.getInterpreter(numStack,operatorStack));
}
}

/**
* 计算结果出栈
* @return
*/
public int calculate() {
return this.numStack.pop().interpret();
}

/**
* 换成标准形式，便于分割
* @param expression
* @return
*/
private String fromat(String expression) {
String result = "";
for (int i = 0; i < expression.length(); i++) {
if (expression.charAt(i) == '(' || expression.charAt(i) == ')' ||
expression.charAt(i) == '+' || expression.charAt(i) == '-' ||
expression.charAt(i) == '*' || expression.charAt(i) == '/')
//在操作符与数字之间增加一个空格
result += (" " + expression.charAt(i) + " ");
else
result += expression.charAt(i);
}
return result;
}
}
``````

``````
public static void main(String[] args) {
System.out.println("result: " + new GPCalculator("10+30/((6-4)*2-2)").calculate());
}
``````

## 2　解释器模式在JDK源码中的应用

``````
public final class Pattern implements java.io.Serializable {
...
private Pattern(String p, int f) {
pattern = p;
flags = f;

if ((flags & UNICODE_CHARACTER_CLASS) != 0)
flags |= UNICODE_CASE;

capturingGroupCount = 1;
localCount = 0;

if (pattern.length() > 0) {
compile();
} else {
root = new Start(lastAccept);
matchRoot = lastAccept;
}
}
...
public static Pattern compile(String regex) {
return new Pattern(regex, 0);
}
public static Pattern compile(String regex, int flags) {
return new Pattern(regex, flags);
}

...
}
``````

## 3　解释器模式在Spring源码中的应用

``````
public interface ExpressionParser {

Expression parseExpression(String expressionString) throws ParseException;

Expression parseExpression(String expressionString, ParserContext context) throws ParseException;

}
``````

``````
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
int result = (Integer) expression.getValue();
System.out.println("计算结果是：" + result);
}
``````

【推荐】Tom弹架构：30个设计模式真实案例（附源码），挑战年薪60W不是梦