一.模式定义
解释器模式(Interpreter Pattern):给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
Interpreter Pattern:Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
二.模式要素
AbstractExpression 抽象表达式:抽象表达式,声明一个抽象的解释操作弗雷,并定义一个抽象的解释方案,其具体的实现在各个具体的子类解释器中完成
TerminalExpression 终结符表达式:终结符表达式,实现文法中终结符有关的解释操作。文法中每一个终结符都有一个具体的终结表达式与之对应
NoterminalExpression 非终结符表达式:非终结表达式,实现文法中非终结符有关的解释操作
Context 环境角色:上下文环境,包含解释器之外的全局信息
三.举例说明
我们通过对算术表达式的解释来看一个解释器模式的实现, 如表达式m+n+p
中,如果我们使用解释器模式对该表达式进行解释,那么m
、n
、p
代表的三个字母可以看成是终结符号,而+
代表的运算符则可以看成是非终结符号。
四.具体代码
AbsExpression.java 抽象表达式
package interpreterpattern;
/**
* author: lllddd
* created on: 2021/3/15 21:55
* description:抽象表达式类
*/
public abstract class AbsExpression {
/**
* 解释执行
*
* @return 解释执行的返回值
*/
public abstract int interpret();
}
VarExpression.java 数值表达式
package interpreterpattern;
/**
* author: lllddd
* created on: 2021/3/15 21:57
* description:值表达式
*/
public class VarExpression extends AbsExpression {
private final int num;
public VarExpression(int num) {
this.num = num;
}
@Override
public int interpret() {
return num;
}
}
AddExpression.java 加法表达式
package interpreterpattern;
/**
* author: lllddd
* created on: 2021/3/15 21:58
* description:加法表达式
*/
public class AddExpression extends AbsExpression {
private AbsExpression left;
private AbsExpression right;
public AddExpression(AbsExpression left, AbsExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
SubExpression.java 减法表达式
package interpreterpattern;
/**
* author: lllddd
* created on: 2021/3/15 21:59
* description:减法表达式
*/
public class SubExpression extends AbsExpression {
private AbsExpression left;
private AbsExpression right;
public SubExpression(AbsExpression left, AbsExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
Calculator.java 计算器
package interpreterpattern;
import java.util.Stack;
/**
* author: lllddd
* created on: 2021/3/15 22:03
* description:运算器
*/
public class Calculator {
private AbsExpression expression;
public Calculator(String inputStr) {
Stack<AbsExpression> expressionStack = new Stack<>();
AbsExpression leftExpression = null;
VarExpression rightExpression = null;
// 根据空格来提取元素
String[] inputArray = inputStr.split(" ");
for (int i = 0; i < inputArray.length; i++) {
if (inputArray[i].equals("+")) {
leftExpression = expressionStack.pop();
rightExpression = new VarExpression(Integer.parseInt(inputArray[++i]));
expressionStack.push(new AddExpression(leftExpression, rightExpression));
} else if (inputArray[i].equals("-")) {
leftExpression = expressionStack.pop();
rightExpression = new VarExpression(Integer.parseInt(inputArray[++i]));
expressionStack.push(new SubExpression(leftExpression, rightExpression));
} else {
expressionStack.push(new VarExpression(Integer.parseInt(inputArray[i])));
}
}
this.expression = expressionStack.pop();
}
/**
* 执行计算
*
* @return 返回计算结果
*/
public int calculate() {
return expression.interpret();
}
}
Main.java 调用类
package interpreterpattern;
/**
* author: lllddd
* created on: 2021/3/15 21:01
* description:调用类
*/
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator("3 + 10 - 8 + 11 - 1");
System.out.println(calculator.calculate());
}
}
运行结果:
五.总结
1.解释器模式的优点
解释器是一个简单语法分析工具,它最显著的特点就是扩展性,修改语法规则只需要修改相应的非终结符表达式即可,若要扩展语法,只要增加非终结符类即可。
2.解释器模式的缺点
(1)解释器模式会引起类膨胀
(2)解释器模式采用递归调用方法
(3)效率问题
3.解释器模式的适用场景
(1)重复发生的问题可以使用解释器模式
(2)一个简单语法需要解释的场景