解释器(Interpreter)模式


    解释器模式是一种行为模式,比较通用的定义“给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子”。spring的express中就使用了这种设计模式。
    解释器模式的本质就是解释自定义了的语言,其中涉及三个概念:表达式(Expression)、解释器(Interpreter)和环境(Context)。
    解释器模式大致分为三个过程:首先,定义一种语言,并定义这种语言的一种文法表现——可以理解为一个运算表达式(Expression);然后,定义解释器(Interpreter)来解释自定义运算表达式;解释器在解释表达式的过程中可能遇到一些变量,而这些变量的值就存储在环境(Context)中,简单的做法是使用Map将变量名和变量值对应起来。

    先来看表达式,表达式分为:终结表达式(Terminal Expression)和非中介表达式(NonTerminal Expression)。
    1、终结表达式:文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符。通常运行表达式中的常量和变量都是终结表达式,蕴含了着到此就终结了,不用再运算了。
    2、非终结表达式:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。
    在具体实现时,需要抽象一个表达式(Expression)抽象类,终结表达式和非终结表达式都继承该表达式抽象类。
 
public abstract class Expression {

}
public class TerminalExpression extends Expression{
	
}

public class NonTerminalExpression extends Expression{
	
}


    再来看解释器,解释器需要提供一个解释方法(interpret)负责文法/表达式的解释工作。解释器模式中将解释器与表达式绑定起来,来表明表达式用该解释器来解释自己。具体实现方式是在表达式中添加解释方法(interpret),表达式可以自己解释自己,无需外部担心。

public class Context{
}

public abstract class Expression {
	public abstract Object interpret(Context context);
}

public class TerminalExpression extends Expression{
	public Object interpret(Context context){}
}

public class NonTerminalExpression extends Expression{
	public Object interpret(Context context){}
}

   
    在解释表达式的过程中可能要替换“变量”,因此定义了Context(环境)类,interpret解释方法接收Context类型的参数。

    在解释器模式中通常还会遇到一个问题,就是递归解释。下面用一个简单的示例,来说明如何使用解释器模式,同时也展示了递归解释。示例定义一个简单加法运算,AndExpression加运算表达式同时解释加运算,VariableExpression变量表达式同时解释变量值:


public class Context {
	private Map<String,Integer> map = new HashMap<String,Integer>();
	public void put(String key, int value){
		map.put(key, value);
	}
	public int lookup(String key){
		return map.get(key);
	}
}


public abstract class Expression {
	public abstract int interpret(Context context);
}



//TerminalExpression
public class VariableExpression extends Expression{
	private String key;
	
	public VariableExpression(String key){
		this.key = key;
	}
	@Override
	public int interpret(Context context) {
		return context.lookup(key);
	}
}


//NonTerminalExpression
public class AndExpression extends Expression{
	
	private Expression left;
	private Expression right;
	
	public AndExpression(Expression left, Expression right){
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		//递归解释
		return left.interpret(context) + right.interpret(context);
	}
}


public class ExpressionMain {

	public static void main(String[] args){
		VariableExpression one = new VariableExpression("one");
		VariableExpression two = new VariableExpression("two");
		VariableExpression three = new VariableExpression("three");
		
		AndExpression first = new AndExpression(one, two);
		AndExpression second = new AndExpression(first, three);
		
		Context context = new Context();
		context.put("one", 1);
		context.put("two", 2);
		context.put("three", 3);
		
		System.out.println(second.interpret(context));
	}
}


猜你喜欢

转载自hoocen.iteye.com/blog/2315170
今日推荐