行為型設計模式 – 解釋器模式詳解
基本介紹
解釋器模式(Interpreter Pattern)提供了評估語言的語法或表達式的方式,它屬於行為型模式。這種模式實現了一個表達式介面,該介面解釋一個特定的上下文。
給定一個語言,定義它的文法表示,並定義一個解釋器,這個解釋器使用該標識來解釋語言中的句子。
該模式對於複雜的場景實現起來比較困難,實際應用較少,大家了解即可。
模式結構

Context(環境角色):聲明一個所有具體表達式都要實現的抽象介面(或者抽象類),介面中主要是一個interpret() 方法,稱為解釋操作。具體解釋任務由它的各個實現類來完成,具體的解釋器分別由終結符解釋器 TerminalExpression 和非終結符解釋器 NonterminalExpression 完成。
AbstractExpression(抽象解釋器):實現與文法中的元素相關聯的解釋操作,通常一個解釋器模式中只有一個終結符表達式,但有多個實例,對應不同的終結符。終結符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在裡面 R1 和 R2 就是終結符,對應的解析 R1 和 R2 的解釋器就是終結符表達式。
TerminalExpression(終結符表達式):文法中的每條規則對應於一個非終結符表達式,非終結符表達式一般是文法中的運算符或者其他關鍵字,比如公式 R=R1+R2 中,+ 就是非終結符,解析 + 的解釋器就是一個非終結符表達式。非終結符表達式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符表達式。
NoterminalExpression(非終結符表達式):這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如 R=R1+R2,我們給 R1 賦值 100,給 R2 賦值 200。這些資訊需要存放到環境角色中,很多情況下我們使用 Map 來充當環境角色就足夠了。
舉例說明
使用解釋器模式實現數字的加減法
1、抽象解釋器
/**
* 抽象解釋器
*/
public abstract class AbstractExpression {
public abstract int interpret(Context context);
}
2、非終結符表達式
/**
* 非終結表達式:加法
*/
public class AddExpression extends AbstractExpression {
private final AbstractExpression left;
private final AbstractExpression right;
public AddExpression(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 SubExpression extends AbstractExpression {
private final AbstractExpression left;
private final AbstractExpression right;
public SubExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
3、終結表達式
/**
* 終結表達式:變數
*/
public class Variable extends AbstractExpression {
private final String key;
public Variable(String key) {
this.key = key;
}
@Override
public int interpret(Context context) {
return context.getValue(key);
}
}
4、環境角色
/**
* 環境上下文
*/
public class Context {
private final Map<String, Integer> valueMap = new HashMap<>();
public void addValue(final String key, final int value) {
valueMap.put(key, value);
}
public int getValue(final String key) {
return valueMap.get(key);
}
public Map<String, Integer> getValueMap() {
return valueMap;
}
}
5、測試類
public class Client {
@Test
public void test(){
Context context = new Context();
context.addValue("a", 6);
context.addValue("b", 9);
context.addValue("c", 1);
Variable a = new Variable("a");
Variable b = new Variable("b");
Variable c = new Variable("c");
AbstractExpression addValue = new AddExpression(a, b);
AbstractExpression subValue = new SubExpression(addValue, c);
System.out.println(context.getValueMap());
System.out.println("a + b - c = " + subValue.interpret(context));
}
}
6、運行結果
{a=6, b=9, c=1}
a+b-c=14
模式分析
優點:
- 可擴展性比較好,靈活
- 增加了新的解釋表達式的方式
- 易於實現簡單文法
缺點:
- 可利用場景比較少
- 對於複雜的文法比較難維護
- 解釋器模式會引起類膨脹
- 解釋器模式採用遞歸調用方法
適用場景:
- 有一個簡單的語法規則,比如一個 sql 語句,如果我們需要根據 sql 語句進行 rm 轉換,就可以使用解釋器模式來對語句進行解釋。
- 一些重複發生的問題,比如加減乘除四則運算,但是公式每次都不同,有時是 a+b-cd,有時是 ab+c-d,等等等等個,公式千變萬化,但是都是由加減乘除四個非終結符來連接的,這時我們就可以使用解釋器模式。

