解释器模式是一种行为型模式,它的主要作用是用一种方式来实现对表达式或文法的处理。我们可以使用解释器模式处理语言的解析,在设计计算机语言的时候解释器模式很有用处。
解释器模式可能需要用到一点编译原理的知识。不过我自己编译原理的内容都忘光了,所以这里不做编译原理的任何介绍了。直接来看代码吧。我们来做一个不含括号的四则运算的解释器。
解释器模式首先需要一个表达式接口,其中有一个方法用于解析表达式的值。
public interface Expression {
int interpret(Context context);
}
之后来考虑一些具体的表达式。首先是常量表达式,这个很简单,直接返回常量的值即可。
class Constant implements Expression {
private int i;
public Constant(int i) {
this.i = i;
}
@Override
public int interpret(Context context) {
return i;
}
}
然后是变量,变量的值保存在上下文中,在编译领域也可以叫做符号表之类的,反正都是一个意思。
class Variable implements Expression {
@Override
public int interpret(Context context) {
return context.getValue(this);
}
}
上下文,或者叫符号表,是保存变量值的地方。我们在Java中可以简单的使用Map来当做符号表。
public class Context {
private HashMap<Variable, Integer> map = new HashMap<>();
public void putValue(Variable name, int value) {
map.put(name, value);
}
public int getValue(Variable name) {
return map.get(name);
}
}
然后是加减乘除四种表达式。这个非常简单,没啥说的吧。
class Add implements Expression {
private Expression a, b;
public Add(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) + b.interpret(context);
}
}
class Sub implements Expression {
private Expression a, b;
public Sub(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) - b.interpret(context);
}
}
class Mul implements Expression {
private Expression a, b;
public Mul(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) * b.interpret(context);
}
}
class Div implements Expression {
private Expression a, b;
public Div(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) / b.interpret(context);
}
}
这些类都准备好之后,我们就可以测试一下解释器模式了。我们手动创建一个表达式,然后调用它的interpret()
方法对其求值。之后,表达式就会如我们所愿的给出结果。
public void run() {
Variable a = new Variable();
Variable b = new Variable();
Context context = new Context();
context.putValue(a, 3);
context.putValue(b, 4);
//a+b*(a-b)+2
Expression expression = new Add(a, new Add(new Mul(b, new Sub(a, b)), new Constant(2)));
System.out.println("a+b*(a-b)+2=" + expression.interpret(context));
}
当然,这只是一个非常简单的小例子,因为new Add(a, new Add(new Mul(b, new Sub(a, b)), new Constant(2)))
这个表达式树是我们手动创建的。如果我们希望更加实用的话,就需要自己编写程序,解析字符串,然后转换为抽象语法树。这就属于编译原理的话题了。