解释器模式(interpreter)
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
在GoF23种设计模式中,属于行为型模式( Behavioral Patterns)
。
对于一种特定的高频发生的问题,我们就可以通过解释器模式应对,定义一个特定的语法,执行特定的解析从而减少问题的发生。
比如,我们开发中会遇到很多指标计算问题,日常编码是写死一个个的指标计算。这样的系统难以拓展,每增加新的指标,我们都要新增代码或修改之前的代码。
如果,我们定义一种新语法,来抽象指标的计算,把变量与计算符号分离,这样就可以动态配置指标计算,而不增加系统的复杂程度,类似groovy脚本
、SpEL表达式
等。
- 优点
- 易于改变和系统拓展
- 缺点
- 语法规则复杂而难以维护
- 使用场景
- 用于解决高频的特定问题
实例
角色说明
- AbstractExpression
- 抽象表达式
- 表达式的统一接口
- TerminalExpression
- 终结符表达式
- 运算符号
- NonterminalExpression
- 非终结符表达式
- 运算变量
- Context
- 上下文
- Client
- 使用者
举例
我们将设计一个简单加减运算表达式。
为了对计算机友好,我们表达式采用逆波兰表达式(也叫后缀表达式)。
通过解析逆波兰表达式
,得到简单运算式的结果。
角色说明
- Expression(AbstractExpression)
- 表达式的统一接口
- MinusExpression(TerminalExpression)
- 终结符表达式
- 减号
- PlusExpression(TerminalExpression)
- 终结符表达式
- 加号
- KeyExpression(NonterminalExpression)
- 非终结符表达式
- 占位符key
- ValueExpression(NonterminalExpression)
- 非终结符表达式
- 实际变量
- Context
- 上下文
- Evaluator(Client)
- 封装解析过程
- Client
- 使用者
code
- Expression.java
public interface Expression {
int interpreter(Context context);
}
- MinusExpression.java
public class MinusExpression implements Expression {
private Expression left;
private Expression right;
public MinusExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
return left.interpreter(context) - right.interpreter(context);
}
}
- PlusExpression.java
public class PlusExpression implements Expression {
private Expression left;
private Expression right;
public PlusExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
return left.interpreter(context) + right.interpreter(context);
}
}
- KeyExpression.java
public class KeyExpression implements Expression{
private String variable;
public KeyExpression(String variable) {
this.variable = variable;
}
@Override
public int interpreter(Context context) {
return context.getValue(variable);
}
}
- ValueExpression.java
public class ValueExpression implements Expression{
private int value;
public ValueExpression(int value) {
this.value = value;
}
@Override
public int interpreter(Context context) {
return value;
}
}
- Context.java
public class Context {
private Map<String, Expression> interpreterMap;
public Context(Map<String, Expression> interpreterMap) {
this.interpreterMap = interpreterMap;
}
public int getValue(String key) {
if (interpreterMap.containsKey(key)) {
return interpreterMap.get(key).interpreter(this);
}
return 0;
}
}
- Evaluator.java
public class Evaluator {
private final static String SEPARATOR = " ";
private final static String PLUS = "+";
private final static String MINUS = "-";
public int parse(String expression) {
Stack<Expression> expressionStack = new Stack<>();
for (String token : expression.split(SEPARATOR)) {
switch (token) {
case PLUS:
Expression plusExpression = new PlusExpression(expressionStack.pop(), expressionStack.pop());
expressionStack.push(plusExpression);
break;
case MINUS:
//栈后进先出,先出为右,后出为左
Expression right = expressionStack.pop();
Expression left = expressionStack.pop();
Expression minusExpression = new MinusExpression(left, right);
expressionStack.push(minusExpression);
break;
default:
expressionStack.push(new ValueExpression(Integer.parseInt(token)));
}
}
return expressionStack.pop().interpreter(null);
}
public int parse(String expression, Context context) {
Stack<Expression> expressionStack = new Stack<>();
for (String token : expression.split(SEPARATOR)) {
switch (token) {
case PLUS:
Expression plusExpression = new PlusExpression(expressionStack.pop(), expressionStack.pop());
expressionStack.push(plusExpression);
break;
case MINUS:
Expression right = expressionStack.pop();
Expression left = expressionStack.pop();
Expression minusExpression = new MinusExpression(left, right);
expressionStack.push(minusExpression);
break;
default:
expressionStack.push(new KeyExpression(token));
}
}
return expressionStack.pop().interpreter(context);
}
}
- Client.java
public class Client {
public static void main(String[] args) {
//语法执行器
Evaluator evaluator = new Evaluator();
//计算 5+10+42-12
//标准执行
String expression = "a b c d - + +";
Map<String, Expression> expressionMap = new HashMap<>(16);
expressionMap.put("a", new ValueExpression(5));
expressionMap.put("b", new ValueExpression(10));
expressionMap.put("c", new ValueExpression(42));
expressionMap.put("d", new ValueExpression(12));
int result = evaluator.parse(expression, new Context(expressionMap));
System.out.println(result);
//简化执行
String expression1 = "5 10 42 12 - + +";
int result1 = evaluator.parse(expression1);
System.out.println(result1);
}
}
- output
45
45
实例
code:org.springframework.expression.Expression
- Test.java
public class Test {
public static void main(String[] args) {
SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
org.springframework.expression.Expression expression = spelExpressionParser.parseExpression("100*2+200");
int value = (int) expression.getValue();
System.out.println(value); //output 400
}
}
如果maven没有引入,请引入以下到pom中。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
总结
解析器模式可以定义简单预发来解决高频特定问题。但是由于该模式难于维护,对于复杂的语言解析还需从长计议啊。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名,转载请标明出处
最后编辑时间为: