一、简介

Interpreter模式(解释器模式),通常是用来解析一门语言,如sql解析。
架构如下:
设计模式之Interpreter模式

  • AbstractInterpreter 定义interpret操作
  • TerminalInterpreter 终态节点
  • NonTerminalInterpreter 非终态节点,内部调用其他的Interpreter
  • Context 上下文对象,存放所有Interpreter共享的信息

Interpreter模式和Composite模式相似,最终将构造为一颗语法树。

以算术表达式"+ – 9 8 7"为例:
设计模式之Interpreter模式

二、使用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);
	}
}

设计模式之Interpreter模式

相关文章:

  • 2022-12-23
  • 2021-12-27
  • 2021-12-07
  • 2022-12-23
  • 2021-06-25
  • 2021-10-04
  • 2021-06-10
猜你喜欢
  • 2021-08-28
  • 2022-12-23
  • 2021-06-02
  • 2021-11-13
  • 2021-06-14
  • 2021-09-19
  • 2022-12-23
相关资源
相似解决方案