首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 解釋器模式深度解析:從文法定義到算式解析器實作

     編輯:Java 相關知識

前言:何時需要解釋器模式?

當系統須處理特定領域語言(DSL)、規則引擎、數學表達式、SQL 解析等「文法固定、頻繁解釋」的問題時,解釋器模式提供結構化的解決方案。雖日常開發較少直接用到,但理解其結構有助於掌握編譯器原理與框架設計思維。

模式結構五大角色

  1. AbstractExpression(抽象表達式): 宣告 interpret(Context) 抽象方法。
  2. TerminalExpression(終結符表達式): 對應文法中的終結符(如變數、常數),每個符號一個實例。
  3. NonterminalExpression(非終結符表達式): 對應文法規則(如加減乘除),持有子表達式引用,遞歸解釋。
  4. Context(上下文): 儲存全域資訊(如變數值映射表)。
  5. Client(客戶端): 建構抽象語法樹(AST)並觸發解釋。

實戰範例:四則運算解析器

文法定義

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 同理...

客戶端建構 AST 並計算 (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,缺乏標準解析器生成器支援

適用: 文法簡單、效能非關鍵、需動態解釋業務規則(如報表公式、權限表達式、簡易腳本語言)。

進階提示

  • 終結符重複度高時可套用享元模式共享實例。
  • 實際專案建議使用 ANTLR、JavaCC 等解析器生成器,自動由文法生成 AST 與解釋器骨架。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved