定义:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
设计类图:
解释器模式中的角色:
- Expression抽象表达式:声明一个所有的具体表达式都需要实现的抽象接口;这个接口主要是一个interpret()方法,称做解释操作。
- Terminal Expression终结符表达式:实现了抽象表达式所要求的接口;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如公式R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
- Nonterminal Expression非终结符表达式:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。
- Context环境:它的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,给R1赋值100,给R2赋值200,这些信息需要存放到环境中。
示例代码:
public abstract class Expression {
public abstract int interpret(Context context);
}
public class NumExpression extends Expression {
private int value;
public NumExpression(int value) {
this.value = value;
}
@Override
public int interpret(Context context) {
return context.lookup(this);
}
public int getValue() {
return value;
}
}
public class AddExpression extends Expression {
private Expression mExpression1;
private Expression mExpression2;
public AddExpression(Expression expression1, Expression expression2) {
this.mExpression1 = expression1;
this.mExpression2 = expression2;
}
@Override
public int interpret(Context context) {
return mExpression1.interpret(context) + mExpression2.interpret(context);
}
}
public class SubExpression extends Expression {
private Expression mExpression1;
private Expression mExpression2;
public SubExpression(Expression expression1, Expression expression2) {
this.mExpression1 = expression1;
this.mExpression2 = expression2;
}
@Override
public int interpret(Context context) {
return mExpression1.interpret(context) - mExpression2.interpret(context);
}
}
public class Context {
public int lookup(NumExpression numExpression) {
return numExpression.getValue();
}
}
public class Calculator {
private Stack<Expression> mExpressionStack = new Stack<>();
private Context mContext;
public Calculator(Context context) {
mContext = context;
}
public int calculate(String expression) {
Expression expression1;
Expression expression2;
String[] elements = expression.split("");
for (int i = 0; i < elements.length; ++i) {
switch (elements[i].charAt(0)) {
case '+':
expression1 = mExpressionStack.pop();
expression2 = new NumExpression(Integer.valueOf(elements[++i]));
mExpressionStack.push(new AddExpression(expression1, expression2));
break;
case '-':
expression1 = mExpressionStack.pop();
expression2 = new NumExpression(Integer.valueOf(elements[++i]));
mExpressionStack.push(new SubExpression(expression1, expression2));
break;
default:
mExpressionStack.push(new NumExpression(Integer.valueOf(elements[i])));
break;
}
}
return mExpressionStack.pop().interpret(mContext);
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context();
Calculator calculator = new Calculator(context);
System.out.println("3+4-5+9 = " + calculator.calculate("3+4-5+9"));
}
}
输出结果:
上面示例代码是简单的模拟了加减算术操作,其中NumExpression就属于Terminal Expression,是一个终结符表达式,而AddExpression和SubExpression就是一个Nonterminal Expression非终结符表达式, 在Calculator类中模拟解析运算表达式,将解析结果不断压栈,最后出栈得到运算结果。
解释器模式是用的比较少的一个模式,它可以用来解释执行固定语法规则的文本。当语法规则比较复杂时,会产生大量的非终结符表达式类文件,因为每一个语法都对应一个类。另外由于解释器内部使用大量的递归调用,这给性能效率和调试会带来很大麻烦。因此解释器只适用于语法规则比较简单的文本。
参考: