解释器模式
一、解释器模式介绍
1、定义与类型
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
为了解释一种语言,而为语言创建的解释器
类型:行为型
2、适用场景
某个特定类型问题发生频率足够高
3、优点
语法由很多类表示,容易改变及扩展此“语言"
4、缺点
当语法规则数目太多时,增加了系统复杂度
5、相关设计模式
解释器模式和适配器模式
适配器模式是需要预先知道要适配的规则,解释器则是要把规则写好,根据规则执行解释
二、代码示例
模拟场景:模拟计算机解释计算表达式,例如中缀表达式 6 * (100 +11) ,计算机会先转换为后缀运算符 6 100 11 + * ,转换过程此处省略,再依次入栈,遇到运算符则出栈中的两个数字进行计算,再将计算结果入栈。
此处需要补充知识点:计算机如何计算我们的表达式的,可参考https://wenku.baidu.com/view/3ff189a15ef7ba0d4a733bb5.html中的表达式求值
解释器接口:
public interface Interpreter {
int interpret();
}
数字解释器:
public class NumberInterpreter implements Interpreter {
private int number;
public NumberInterpreter(int number) {
this.number = number;
}
public NumberInterpreter(String number) {
this.number = Integer.valueOf(number);
}
@Override
public int interpret() {
return this.number;
}
}
加法解释器:
public class AddInterpreter implements Interpreter {
private Interpreter firstExpression, secondExpression;
public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
this.firstExpression = firstExpression;
this.secondExpression = secondExpression;
}
@Override
public int interpret() {
return this.firstExpression.interpret() + this.secondExpression.interpret();
}
@Override
public String toString() {
return "+";
}
}
乘法解释器:
public class MultiInterpreter implements Interpreter {
private Interpreter firstExpression, secondExpression;
public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
this.firstExpression = firstExpression;
this.secondExpression = secondExpression;
}
@Override
public int interpret() {
return this.firstExpression.interpret() * this.secondExpression.interpret();
}
@Override
public String toString() {
return "*";
}
}
运算符工具类:
public class OperatorUtil {
public static boolean isOperator(String symbol) {
return (symbol.equals("+") || symbol.equals("*"));
}
public static Interpreter getExpressionObject(Interpreter firstExpression, Interpreter secondExpression, String symbol) {
if (symbol.equals("+")) {
return new AddInterpreter(firstExpression, secondExpression);
} else if (symbol.equals("*")) {
return new MultiInterpreter(firstExpression, secondExpression);
}
return null;
}
}
转换器类:
public class MyExpressionParser {
private Stack<Interpreter> stack = new Stack<Interpreter>();
public int parser(String str) {
String[] strItemArray = str.split(" ");
for (String symbol : strItemArray) {
if (!OperatorUtil.isOperator(symbol)) {
Interpreter numberExpression = new NumberInterpreter(symbol);
stack.push(numberExpression);
System.out.println(String.format("入栈:%d", numberExpression.interpret()));
} else {
// 是运算符,可以计算
Interpreter firstExpression = stack.pop();
Interpreter secondExpression = stack.pop();
System.out.println(String.format("出栈:%d 和 %d", firstExpression.interpret(), secondExpression.interpret()));
Interpreter operator = OperatorUtil.getExpressionObject(firstExpression, secondExpression, symbol);
System.out.println(String.format("应用运算符:%s", operator));
int result = operator.interpret();
NumberInterpreter resultExpression = new NumberInterpreter(result);
stack.push(resultExpression);
System.out.println(String.format("阶段结果入栈:%d", resultExpression.interpret()));
}
}
int result = stack.pop().interpret();
return result;
}
}
测试类:
public class Test {
public static void main(String[] args) {
String inputStr = "6 100 11 + *";
MyExpressionParser expressionParser = new MyExpressionParser();
int result = expressionParser.parser(inputStr);
System.out.println(result);
}
}
输出:
入栈:6
入栈:100
入栈:11
出栈:11 和 100
应用运算符:+
阶段结果入栈:111
出栈:111 和 6
应用运算符:*
阶段结果入栈:666
666
三、源码示例
1、JDK中的正则Pattern
2、spring中的El表达式
测试:
public class SpringTest {
public static void main(String[] args) {
org.springframework.expression.ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("6 * (100 + 11)");
int result = (Integer) expression.getValue();
System.out.println(result);
}
}
输出:666