當系統須處理特定領域語言(DSL)、規則引擎、數學表達式、SQL 解析等「文法固定、頻繁解釋」的問題時,解釋器模式提供結構化的解決方案。雖日常開發較少直接用到,但理解其結構有助於掌握編譯器原理與框架設計思維。
interpret(Context) 抽象方法。Expression ::= Term { ('+' | '-') Term }*
Term ::= Factor { ('*' | '/') Factor }*
Factor ::= Number | Variable | '(' Expression ')'
// Context: 變數值存儲
class Context {
private Map<Variable, Integer> vars = new HashMap<>();
void assign(Variable v, int val) { vars.put(v, val); }
int lookup(Variable v) { return vars.get(v); }
}
// 抽象表達式
abstract class Expression {
abstract int interpret(Context ctx);
}
// 終結符: 常數
class Constant extends Expression {
private final int value;
Constant(int v) { value = v; }
int interpret(Context ctx) { return value; }
}
// 終結符: 變數
class Variable extends Expression {
private final String name;
Variable(String n) { name = n; }
int interpret(Context ctx) { return ctx.lookup(this); }
// equals/hashCode 基於 name 實作,供 Map 使用
}
// 非終結符: 加法
class Add extends Expression {
private final Expression left, right;
Add(Expression l, Expression r) { left = l; right = r; }
int interpret(Context ctx) { return left.interpret(ctx) + right.interpret(ctx); }
}
// Subtract, Multiply, Division 同理...
(a*b)/(a-b+2)public class Test {
public static void main(String[] args) {
Context ctx = new Context();
Variable a = new Variable("a"), b = new Variable("b");
ctx.assign(a, 5); ctx.assign(b, 7);
Constant two = new Constant(2);
Expression expr = new Div(
new Mul(a, b),
new Add(new Sub(a, b), two)
);
System.out.println("結果: " + expr.interpret(ctx)); // 輸出 35 / (5-7+2) = 35/0 -> 例外處理
}
}
| 優點 | 缺點 |
|---|---|
| 易於新增/修改文法規則(只需新增類別) | 文法規則多時類別爆炸,維護困難 |
| 每條規則獨立封裝,符合單一職責 | 遞歸解釋效率較低,不適合高效能場景 |
| 可輕鬆實作複雜嵌套表達式 | 需自行建構 AST,缺乏標準解析器生成器支援 |
適用: 文法簡單、效能非關鍵、需動態解釋業務規則(如報表公式、權限表達式、簡易腳本語言)。