解譯器模式

📢 本文由 gemini-2.5-flash 翻譯

解譯器模式 (Interpreter Pattern) 類行為型模式

意圖

給定一種語言,定義其文法的一種表示法,並定義一個解譯器,此解譯器會使用該表示法來解譯語言中的句子。

結構

解譯器模式

其中:

  • AbstractExpression 宣告一個程式的解譯操作,此介面為抽象語法樹中所有節點所共享。
  • TerminalExpression 實作與文法中終端符號相關聯的解譯操作;一個句子中的每個終端符號需要該類別的一個實例。
  • NonterminalExpression 對文法中的每一條規則都需要一個 NonterminalExpression 類別;為每個符號都維護一個 AbstractExpression 類型的實例變數;為文法中的非終端符號實作解譯 (Interpret) 操作。
  • Context 包含解譯器之外的一些全域資訊。
  • Client 建構 (或被給定) 表示該文法所定義語言中一個特定句子的抽象語法樹,該抽象語法樹由 NonterminalExpression 和 TerminalExpression 的實例組裝而成;呼叫解譯操作。

適用性

解譯器模式適用於當有一種語言需要解譯執行,且可將該語言中的句子表示為一個抽象語法樹時,以下情況效果最佳:

  • 該文法簡單。
  • 效率不是一個關鍵問題。

範例

檢查字串:某區域的某人員 (someone of ? region)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.util.*;

public class InterpreterPattern {
    public static void main(String[] args) {
        Context context = new Context();

        context.check("developer of A region");
    }
}

class Context{
    private String[] regions = {"A region", "B region", "C region"};
    private String[] persons = {"developer", "tester"};

    private NonterminalExpression nte;

    public Context(){
         TerminalExpression region = new TerminalExpression(regions);
         TerminalExpression person = new TerminalExpression(persons);
         nte = new NonterminalExpression(region, person);
    }

    public void check(String info){
        boolean bool = nte.Interpret(info);
        if(bool){
            System.out.println("正確");
        }else {
            System.out.println("錯誤");
        }
    }
}

interface Expression{
    public boolean Interpret(String info);
}

class NonterminalExpression implements Expression{
    TerminalExpression region;
    TerminalExpression person;
    public NonterminalExpression(TerminalExpression region, TerminalExpression person){
        this.person = person;
        this.region = region;
    }

    @Override
    public boolean Interpret(String info){
        String[] str = info.split(" of ");
        // "developer of A region" --> str = {"developer", "A region"}
        return region.Interpret(str[1]) && person.Interpret(str[0]);
    }
}

class TerminalExpression implements Expression{
    private Set<String> set = new HashSet<>();

    public TerminalExpression(String[] data){
        for(String str : data){
            set.add(str);
        }
    }

    @Override
    public boolean Interpret(String info){
        return set.contains(info);
    }
}