Java中的解释器模式
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。使用解释器模式为语言创建解释器。
类型:
通过中间类的行为型模式
解释器模式中的角色:
- 抽象的解释器AbstractExpression:定义解释操作的接口,例如:interpret()
- 终结符表达式TerminalExpression:为文法的终结符实现解释操作。例 : R1+R2=R,R1和R2便是终结符。
- 非终结符表达式NonterminalExpression:为文法的非终结符实现解释操作。例: R1+R2=R,+ 便是终结符。
- 环境对象Context:包含解释器以外的一些全局信息,一般用来存储终结符的具体信息。例 : R1=2,R2=3 用来存储具体的数值。
解释器模式的关系图:
解释器模式示例:
抽象的解释器AbstractExpression:
/**
* Create by zhaihongwei on 2018/4/9
* 抽象的解释器对象
*/
public interface Expression {
/**
* 定义解释器的接口
*/
Integer interpret(Context context);
}
终结符表达式TerminalExpression:
/**
* Create by zhaihongwei on 2018/4/9
* 终结符表达式,用来解释运算符之外的表达式。
*/
public class NumberTerminalExpression implements Expression{
@Override
public Integer interpret(Context context) {
return context.getTerminalValue(this);
}
}
非终结符表达式NonterminalExpression:
/**
* Create by zhaihongwei on 2018/4/9
* 非终结符表达式,说白了就是运算符号,当然你也可以已经定义一种符号来进行某种运算
* 例如 R1 # R2 , 将 # 解释为+ - * / 或者其他的运算。
*/
public class AddNonTerminalExpression implements Expression {
private Expression left;
private Expression right;
public AddNonTerminalExpression(Expression left,Expression right) {
this.left = left;
this.right = right;
}
@Override
public Integer interpret(Context context) {
return context.getTerminalValue(left) + context.getTerminalValue(right);
}
}
环境对象Context:
/**
* Create by zhaihongwei on 2018/4/9
* 环境角色
*/
public class Context {
// 用来存储终结符的具体值
public Map<Expression,Integer> map = new HashMap();
public void addTerminalValue(Expression exp,Integer value) {
map.put(exp,value);
}
public Integer getTerminalValue(Expression exp) {
return map.get(exp);
}
}
测试类:
/**
* Create by zhaihongwei on 2018/4/9
*/
public class InterpreterTest {
public static void main(String[] args) {
// 解释表达式 : 1 # 3 ,将 # 解释为 + ,加法运算
// 终结符表达式
NumberTerminalExpression r1 = new NumberTerminalExpression();
NumberTerminalExpression r2 = new NumberTerminalExpression();
// 非终结符表达式
AddNonTerminalExpression add = new AddNonTerminalExpression(r1,r2);
// 初始化环境角色,并赋值
Context context = new Context();
context.addTerminalValue(r1,1);
context.addTerminalValue(r2,3);
// 输出解释器的结果
System.out.println(add.interpret(context));
}
}
测试结果:
1 # 3 通过解释器的最终结果为:4
总结:
通过解释器模式,做到了将1 # 3 表达式 解释为 1 + 3的算式运算,这种方式便是解释器。但是解释器很少会被使用,你应该也可以看到实现起来的复杂度。
解释器模式的优缺点:
优点:
- 将每一种语法规则都定义为一个单独的类,实现单一职责。
- 语法规则通过许多类的形式表示,容易扩展语法。
缺点:
- 语法规则过多时,产生大量的语法类,使得这些语法类变得难以维护和管理