当想解析一个文件或者其他内容时,可以根据规律自己定义一种文法,并定义一个解释器,然后解析这种文法,以达到解析文件或其他内容的效果
解释器模式的本质:分离实现,解释执行。
解释器模式通过一个解释器对象处理一个语法规则的方式,把复杂的功能分离开;然后选择需要被执行的功能,并把这些功能组合成为需要被解释执行的抽象语法树;再按照抽象语法树来解释执行,实现相应的功能。
建议在以下情况中选用解释器模式。
当有一个语言需要解释执行,并且可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式。
在使用解释器模式的时候,还有两个特点需要考虑,一个是语法相对应该比较简单,太复杂的语法不适合使用解释器模式;另一个是效率要求不是很高,对效率要求很高的情况下,不适合使用解释器模式。
解释器模式有以下优点。.
易于实现语法
在解释器模式中,一条语法规则用一个解释器对象来解释执行。对于解释器的实现来讲,功能就变得比较简单,只需要考虑这一条语法规则的实现就可以了,其他的都不用管。
易于扩展新的语法
正是由于采用一个解释器对象负责一条语法规则的方式,使得扩展新的语法非常容易。扩展了新的语法,只需要创建相应的解释器对象,在创建抽象语法树的时候使用这个新的解释器对象就可以了。
解释器模式的缺点是不适合复杂的语法。
如果语法特别复杂,构建解释器模式需要的抽象语法树的工作是非常艰巨的,再加上有可能会需要构建多个抽象语法树。所以解释器模式不太适合于复杂的语法,对于复杂的语法,使用语法分析程序或编译器生成器可能会更好一些。
解释器模式的核心思想是:定义一种文法,并定义一个解释器,使用该解释器来解释这个文法。
文法:可以将其理解为一种规则,就好比汉语中一句话必须由“主谓宾”三者构成一样。下面的文法是加减操作,只要是加减操作下面的解释器就可以进行解析。
实现一个计算器的加减操作
1.解释器接口及其实现类
/*** @description:解释器接口*/
public interface Expression {/*** 解析表达式* @return*/int interpret();}/*** @description:数值解释器*/
public class NumExpression implements Expression {private int value;public NumExpression(int value) {this.value = value;}@Overridepublic int interpret() {return this.value;}}/*** @description:加法解释器*/
public class AddExpression implements Expression {public Expression left;public Expression right;public AddExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return this.left.interpret() + this.right.interpret();}
}/*** @description:减法解释器*/
public class SubExpression implements Expression {public Expression left;public Expression right;public SubExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return this.left.interpret() - this.right.interpret();}
}
2.上下文类
/*** @description:计算器类(上下文)*/
public class Calculator {//栈private Stack stack = new Stack<>();/*** @author conggq* @description:解释文法方法* @createTime 2022/11/30 13:06*/public int parse(String expression) {String[] elements = expression.split(" ");Expression leftExpr, rightExpr;for (int i = 0; i < elements.length; i++) {String operator = elements[i];if (("+".equals(operator) || "-".equals(operator))) {leftExpr = this.stack.pop();rightExpr = new NumExpression(Integer.valueOf(elements[++i]));if ("+".equals(operator)) {this.stack.push(new AddExpression(leftExpr, rightExpr));} else if ("-".equals(operator)) {this.stack.push(new SubExpression(leftExpr, rightExpr));}} else {NumExpression numInterpreter = new NumExpression(Integer.valueOf(elements[i]));this.stack.push(numInterpreter);}}//等价于new SubExpression(new AddExpression(new NumExpression(10), new NumExpression(30)), new NumExpression(20)).interpret()return this.stack.pop().interpret();}}
3.测试类
/*** @description:测试类*/
public class Client {public static void main(String[] args) {System.out.println("result: " + new Calculator().parse("10 + 30 - 20"));System.out.println("result: " + new SubExpression(new AddExpression(new NumExpression(10), new NumExpression(30)), new NumExpression(20)).interpret());}}
4.结果