设计模式之Interpreter模式

一、简介

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

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

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

以算术表达式"+ – 9 8 7"为例:
设计模式之Interpreter模式_第2张图片

二、使用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,设计模式,Java)