计算机用来解释句子或表达式,类似在软件开发过程中,有时需要处理一系列多次重复出现的问题。如果将这类问题归纳成一种简单的语言,那么这些问题实例将是该语言的一些句子,这样就可以用编译原理中的解释器模式来实现了。
解释器模式的定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解释器来解释语言中的句子,即用编译语言的方式来分析应用中的实例。
解释器模式优点:
解释器模式缺点:
解释器模式类图如下:
使用解释器的方式实现加减运算,例如输入表达式a+b+c-d,a=10,b=50,c=20,d=10,输出计算结果。
新建抽象表达式接口,约定解释器的解释操作,接口名称为Expression,内容如下:
public interface Expression {
/**
* 获取解释结果
* @param map 表达式键值对
* @return 返回解释后的值
*/
Integer interpret(Map<String, Integer> map);
}
在加减运算中,变量不可以继续进行推演运算属于终结符,新建变量表达式类,解释操作返回自身的值,类名为VariableExpression,内容如下:
public class VariableExpression implements Expression {
private String variableKey;
public VariableExpression(String variableKey){
this.variableKey = variableKey;
}
@Override
public Integer interpret(Map<String, Integer> map) {
return map.get(variableKey);
}
}
在加减运算中,运算符号“+”与“-”可以继续推导属于非终结符,新建非终结符表达式基类,定义左右两个表达式属性,类名为SymbolExpression,内容如下:
public class SymbolExpression implements Expression{
protected Expression leftExpression;
protected Expression rightExpression;
public SymbolExpression(Expression leftExpression, Expression rightExpression){
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public Integer interpret(Map<String, Integer> map) {
return 0;
}
}
新建加法非终结符表达式类用来解释加法,类名为AddSymbolExpression,内容如下:
public class AddSymbolExpression extends SymbolExpression{
public AddSymbolExpression(Expression leftExpression, Expression rightExpression) {
super(leftExpression, rightExpression);
}
@Override
public Integer interpret(Map<String, Integer> map) {
return leftExpression.interpret(map) + rightExpression.interpret(map);
}
}
类似新建减法终结符表达式类用来解释减法,类名为SubSymbolExpression,内容如下:
public class SubSymbolExpression extends SymbolExpression {
public SubSymbolExpression(Expression leftExpression, Expression rightExpression) {
super(leftExpression, rightExpression);
}
@Override
public Integer interpret(Map<String, Integer> map) {
return leftExpression.interpret(map) - rightExpression.interpret(map);
}
}
新建环境类用来执行解析表达式,类名为Calculator,内容如下:
public class Calculator {
/**
* 最终表达式
*/
private Expression expression;
public Calculator(String expression) {
char[] charArray = expression.toCharArray();
Stack<Expression> stack = new Stack();
Expression left;
Expression right;
for (int i = 0; i < charArray.length; i++) {
switch (charArray[i]){
case '+':
// 加法运算符表达式构建
left = stack.pop();
right = new VariableExpression(String.valueOf(charArray[++i]));
stack.push(new AddSymbolExpression(left, right));
break;
case '-':
// 减法运算符表达式构建
left = stack.pop();
right = new VariableExpression(String.valueOf(charArray[++i]));
stack.push(new SubSymbolExpression(left, right));
break;
default:
// 操作数进栈
stack.push(new VariableExpression(String.valueOf(charArray[i])));
break;
}
}
this.expression = stack.pop();
}
/**
* 获取表达式结果
* @param map 变量表
* @return 运算结果
*/
public Integer calculate(Map<String, Integer> map){
return expression.interpret(map);
}
}
新建客户端测试,内容如下:
public class Client {
public static void main(String[] args) {
// 准备表达式
String expression = "a+b+c-d";
// 准备变量表
Map<String, Integer> map = new HashMap(){{
put("a", 10);
put("b", 50);
put("c", 20);
put("d", 10);
}};
// 创建解释器上下文
Calculator calculator = new Calculator(expression);
// 获取表达式的结果
Integer result = calculator.calculate(map);
// 打印表达式结果
System.out.println("result = " + result);
}
}
解释器模式适用于表达式被解释并转换为其内部表示的情况。在JAVA的Pattern中实现了解释器模式,它用于解析正则表达式。在解释正则表达式时返回匹配器对象,匹配器使用基于正则表达式的模式类创建的内部结构,使用如下:
public class Test {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaaaaaab");
boolean result = matcher.matches();
System.out.println("result = " + result);
}
}