1. 程式人生 > >直譯器(Interpreter)模式

直譯器(Interpreter)模式

[size=large]
直譯器模式是一種行為模式,比較通用的定義“給定一個語言之後,直譯器模式可以定義出其文法的一種表示,並同時提供一個直譯器。客戶端可以使用這個直譯器來解釋這個語言中的句子”。spring的express中就使用了這種設計模式。
直譯器模式的本質就是解釋自定義了的語言,其中涉及三個概念:表示式(Expression)、直譯器(Interpreter)和環境(Context)。
直譯器模式大致分為三個過程:首先,定義一種語言,並定義這種語言的一種文法表現——可以理解為一個運算表示式(Expression);然後,定義直譯器(Interpreter)來解釋自定義運算表示式;直譯器在解釋表示式的過程中可能遇到一些變數,而這些變數的值就儲存在環境(Context)中,簡單的做法是使用Map將變數名和變數值對應起來。

先來看錶達式,表示式分為:終結表示式(Terminal Expression)和非中介表示式(NonTerminal Expression)。
1、終結表示式:文法中的每一個終結符都有一個具體終結表示式與之相對應。比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符。通常執行表示式中的常量和變數都是終結表示式,蘊含了著到此就終結了,不用再運算了。
2、非終結表示式:文法中的每一條規則都需要一個具體的非終結符表示式,非終結符表示式一般是文法中的運算子或者其他關鍵字,比如公式R=R1+R2中,“+"就是非終結符,解析“+”的直譯器就是一個非終結符表示式。
在具體實現時,需要抽象一個表示式(Expression)抽象類,終結表示式和非終結表示式都繼承該表示式抽象類。
[/size]

public abstract class Expression {

}
public class TerminalExpression extends Expression{

}

public class NonTerminalExpression extends Expression{

}

[size=large]
再來看直譯器,直譯器需要提供一個解釋方法(interpret)負責文法/表示式的解釋工作。直譯器模式中將直譯器與表示式繫結起來,來表明表示式用該直譯器來解釋自己。具體實現方式是在表示式中新增解釋方法(interpret),表示式可以自己解釋自己,無需外部擔心。[/size]

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){}
}

[size=large]
在解釋表示式的過程中可能要替換“變數”,因此定義了Context(環境)類,interpret解釋方法接收Context型別的引數。

在直譯器模式中通常還會遇到一個問題,就是遞迴解釋。下面用一個簡單的示例,來說明如何使用直譯器模式,同時也展示了遞迴解釋。示例定義一個簡單加法運算,AndExpression加運算表示式同時解釋加運算,VariableExpression變量表達式同時解釋變數值:[/size]


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));
}
}