簡介
解釋器模式(Interpreter Pattern)是一種行為型設計模式,這種模式實作了一個運算式介面,該介面解釋一個特定的背景關系,這種模式常被用在 SQL 決議、符號處理引擎等,
解釋器模式常用于對簡單語言的編譯或分析實體中,為了掌握好它的結構與實作,必須先了解編譯原理中的“文法、句子、語法樹”等相關概念,
作用
- 可擴展性比較好,靈活,增加了新的解釋運算式的方式,易于實作簡單文法,
- 在語法樹中的每個運算式節點類都是相似的,所以實作其文法較為容易,
實作步驟
- 創建抽象運算式介面(Expression),各種運算式都要實作該介面,
- 分別創建最終運算式和非最終運算式,最終運算式(這里是VarExpression)沒有子級,直接解釋運算式,非最終運算式(這里是AddExpression和SubtractExpression)是維護子運算式的容器,并將解釋請求轉發給這些運算式,
- 創建背景關系環境類(這里是Context),用來運算式求值時構建執行環境,
- 客戶端呼叫時先建立執行背景關系環境,然后宣告變數,再進行計算,
UML

Java代碼
抽象運算式介面
// Expression.java 抽象運算式介面,根據業務場景規范運算式
public interface Expression {
public int interpret(Context context);
}
具體運算式實作
// AddExpression.java 具體運算式,實作了抽象運算式介面
public class AddExpression implements Expression {
private Expression exprOne = null;
private Expression exprTwo = null;
public AddExpression(Expression exprOne, Expression exprTwo) {
this.exprOne = exprOne;
this.exprTwo = exprTwo;
}
// 覆寫運算式,執行context物件
@Override
public int interpret(Context context) {
System.out.println(this.getClass().getName() + "::interpret() [context = " + context.getClass().getName() + "]");
return exprOne.interpret(context) + exprTwo.interpret(context);
}
}
// SubtractExpression.java 具體運算式,實作了抽象運算式介面
public class SubtractExpression implements Expression {
private Expression exprOne = null;
private Expression exprTwo = null;
public SubtractExpression(Expression exprOne, Expression exprTwo) {
this.exprOne = exprOne;
this.exprTwo = exprTwo;
}
// 覆寫運算式,執行context物件
@Override
public int interpret(Context context) {
System.out.println(this.getClass().getName() + "::interpret() [context = " + context.getClass().getName() + "]");
return exprOne.interpret(context) - exprTwo.interpret(context);
}
}
// VarExpression.java 變數運算式,或者叫終端運算式,其他運算式求值時通過層層追溯最后指向這里
// 變數與執行環境的Key對應,最侄訓通過key獲取傳入的值
public class VarExpression implements Expression {
private String key;
public VarExpression(String key) {
this.key = key;
}
@Override
// 覆寫運算式,根據key獲取變數
public int interpret(Context context) {
return context.get(key);
}
}
執行環境類
// Context.java 構建可執行環境背景關系
public class Context {
private Map<String, Integer> map = new HashMap<>();
public Context(String key, int value) {
this.add(key, value);
}
public Context() {
}
public void add(String key, int value) {
map.put(key, value);
}
public int get(String key) {
return map.get(key);
}
}
// Application.java 呼叫程式,組織各種解釋器
/*
* 解釋器模式先構建執行背景關系Context,然后構建一個最終的獲取值的運算式VarExpression,這就構成了含背景關系和變數-值的基本環境,
* 再將基本環境放到工具運算式里AddExpression或SubtractExpreesion進行計算,最終得到結果,
*/
// 構建兩個數相加的例子
public static int addTwo(int one, int two) {
// 構建執行背景關系環境
Context context = new Context();
context.add("one", one);
context.add("two", two);
// 構建運算式
VarExpression varOne = new VarExpression("one");
VarExpression varTwo = new VarExpression("two");
// 再構建變數來進行計算,看起來啰嗦,但這樣構建多種不同運算式計算就變得簡單
Expression result = new AddExpression(varOne, varTwo);
return result.interpret(context);
}
// 構建連加計算的例子
public static int addMore(int... numbers) {
if (numbers.length <= 1) {
return numbers[0];
}
Context context = new Context();
// 構建執行環境
for (int num : numbers) {
context.add("num" + num, num);
}
// 先取出前兩個作為計算基礎
VarExpression varOne = new VarExpression("num" + numbers[0]);
VarExpression varTwo = new VarExpression("num" + numbers[1]);
// 再構建運算式,先賦值前兩個
Expression expression = new AddExpression(varOne, varTwo);
// 如果只有兩個數則直接回傳計算結果
if (numbers.length == 2) {
return expression.interpret(context);
}
// 如果數量超過兩個則累加運算式再求值
for (int i = 2; i < numbers.length; i++) {
Expression nextExpression = new VarExpression("num" + numbers[i]);
// 運算式不斷累加
expression = new AddExpression(expression, nextExpression);
}
return expression.interpret(context);
}
// 計算前兩個數相加,再減去后一個數的計算例子
public static int addAndSubtract(int one, int two, int three) {
// 構建執行背景關系環境,有3個可操作的域
Context context = new Context();
context.add("one", one);
context.add("two", two);
context.add("three", three);
// 構建運算式,有3個變數
VarExpression varOne = new 