解释器模式
解释器模式是一种类行为型模式,它主要是用来解释特定语言的特定文法表示,虽然这个在实际生产中不常用到,但是我们学习一下还是有帮助的。
定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
使用场景
当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式的效果最好:
1. 该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式,这样可以节省空间而且还可能节省时间。
2. 效率不是一个关键问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另外一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是有用的。
结构
实现
我们用一个加减乘除的例子来说明一下解释器模式,AbstractExpression接口设计及其实现
public abstract class AbstractExpression {
public abstract int interpret(Context context);
}
public class TerminalExpression extends AbstractExpression {
private int i ;
public TerminalExpression(int a){
i = a;
}
@Override
public int interpret(Context context) {
return i;
}
}
public class Add extends AbstractExpression{
private AbstractExpression left ,right ;
public Add(AbstractExpression left, AbstractExpression right){
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}
public class Subtract extends AbstractExpression{
private AbstractExpression left ,right ;
public Subtract(AbstractExpression left, AbstractExpression right){
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
public class Multiply extends AbstractExpression{
private AbstractExpression left ,right ;
public Multiply(AbstractExpression left, AbstractExpression right){
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) * right.interpret(context);
}
}
public class Division extends AbstractExpression{
private AbstractExpression left ,right ;
public Division(AbstractExpression left, AbstractExpression right){
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context)/right.interpret(context);
}
}
Context的设计与实现
public class Context {
private Map<Variable, Integer> valueMap = new HashMap<Variable, Integer>();
public void addValue(Variable x , int y){
Integer yi = new Integer(y);
valueMap.put(x , yi);
}
public int LookupValue(Variable x){
int i = ((Integer)valueMap.get(x)).intValue();
return i ;
}
}
public class Variable extends AbstractExpression{
@Override
public int interpret(Context context) {
return context.LookupValue(this);
}
}
我们来测试一下,计算(a*b)/(a-b+2)
public class Client {
private static AbstractExpression aex ;
private static Context con ;
public static void main(String[] args) {
con = new Context();
//设置变量、常量
Variable a = new Variable();
Variable b = new Variable();
TerminalExpression c = new TerminalExpression(2);
//为变量赋值
con.addValue(a , 5);
con.addValue(b , 7);
//运算,对句子的结构由我们自己来分析,构造
aex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c));
System.out.println("运算结果为:"+ aex.interpret(con));
}
}
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。解释器模式用来做各种各样的解释器,如正则表达式等的解释器等等。