定義
解釋器模式(Interpreter Pattern):給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
結構
- AbstractExpression(抽象語法):在抽象表達式中聲明瞭抽象的解釋操作,它是所有終結符表達式和非終結表達式的公共父類。
- TerminalExpression(終結符表達式):終結符表達式是抽象表達式的子類,它實現了與文法中的終結符相關聯的解釋操作,在句子中的每一個終結符都是該類的一個實例。通常在一個解釋器模式中只有少數幾個終結符表達式類,他們的實例可以通過非終結符表達式組成較爲複雜的句子。
- NonterminalExpression(非終結符表達式):非終結符表達式也是抽象表達式的子類,它實現了文法中非終結符的解釋操作,由於在非終結符表達式中可以包含終結符表達式,也可以繼續包含非終結符表達式,因此其解釋操作一般通過遞歸的方式完成。
- Context(環境類):環境類又稱爲上下文類,它用於儲存解釋器之外的一些全局信息,通常它臨時存儲了需要解釋的語句。
代碼
Context
import java.util.HashMap;
import java.util.Map;
public class Context {
private Map<String, String> map = new HashMap<>();
public void assign(String key, String value) {
// 往環境類中設值
map.put(key, value);
}
public String lookup(String key) {
// 獲取儲存在環境類中的值
return map.get(key);
}
}
AbstractExpression
public abstract class AbstractExpression {
public abstract void interpret(Context context);
}
TerminalExpression
public class TerminalExpression extends AbstractExpression {
@Override
public void interpret(Context context) {
// 終結符表達式的解釋操作
System.out.println("TerminalExpression");
}
}
NonterminalExpression
public class NonterminalExpression extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
public NonterminalExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public void interpret(Context context) {
// 遞歸調用每一個組成部分的interpret()方法
// 在遞歸調用時指定組成部分的連接方式,即非終結符的功能
}
}
優/缺點與適用環境
- 優點
- 易於改變和擴展文法。由於在解釋器模式中使用類表示語言的文法規則,因此可以通過集成等機制來改變或擴展文法。
- 沒一條文法規則都可以表示爲一個類,因此可以方便地實現一個簡單的語言。
- 實現文法較爲容易。在抽象語法樹中每一個表達式結點類的實現方式都是相似的,這些類的代碼編寫都不會特別複雜,還可以通過一些工具自動生成結點類代碼。
- 增加新的解釋表示式方式較爲方便。如果用戶要增加新的解釋表示式只需要對應增加一個新的終結符表達式或非終結符表達式類,原有表達式類代碼無須修改,符合開閉原則。
- 缺點
- 對於複雜的文法難以維護。在解釋器模式中每一條規則至少需要定義一個類,因此如果一個語言包含太多文法規則,類的個數將會急劇增加,導致系統難以管理和維護,此時可以考慮使用語法分析程序等方式來取代解釋器模式。
- 執行效率低。由於在解釋器模式中使用了大量的循環和遞歸調用,因此在解釋較爲複雜的句子時其速度很慢,而且代碼的調試過程也比較麻煩。
- 適用環境
- 可以將一個需要解釋執行的語言中的句子表示爲一顆抽象語法樹。
- 一些重複出現的問題可以用一種簡單的語言進行表達。
- 一個語言的文法較爲簡單。對於複雜的文法,解釋器模式中的文法類層次結構將變得很龐大而無法管理,此時最好使用語法分析程序生成器。
- 執行效率不是關鍵問題。高效的解釋器通常不是通常直接解析抽象語法樹來實現的,而是需要將他們轉換成其他形式,使用解釋器模式的執行效率並不高。