cover

Interpreter 模式:把語法變成可執行規則

Interpreter 模式為語言定義語法規則,讓系統能解讀特定語法並執行。

classDiagram
    class InterpreterContext {
        -text : String
        +getText() String
        +setText(text) void
    }
    class InterpreterRule {
        <<abstract>>
        +interpret(context)* Context
    }
    class BoldInterpreter {
        +interpret(context) Context
    }
    class ItalicInterpreter {
        +interpret(context) Context
    }
    class MarkdownInterpreter {
        -rules : InterpreterRule[]
        +addRule(rule) void
        +interpret(context) String
    }
    InterpreterRule <|-- BoldInterpreter
    InterpreterRule <|-- ItalicInterpreter
    MarkdownInterpreter o-- InterpreterRule : 依序執行
    MarkdownInterpreter ..> InterpreterContext : 傳入解析

使用情境

  1. Markdown 解析:轉成 HTML。
  2. 數學表達式:解析並計算。
  3. DSL:領域專用語言。

實作範例

Interpreter 模式:文本經過濾鏡逐步轉換

class InterpreterContext {
  constructor(text) {
    this.text = text;
  }
 
  getText() {
    return this.text;
  }
 
  setText(text) {
    this.text = text;
  }
}
 
class InterpreterRule {
  interpret(context) {
    throw new Error('interpret must be implemented');
  }
}
 
class BoldInterpreter extends InterpreterRule {
  interpret(context) {
    let text = context.getText();
    text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
    context.setText(text);
    return context;
  }
}
 
class ItalicInterpreter extends InterpreterRule {
  interpret(context) {
    let text = context.getText();
    text = text.replace(/\*(.*?)\*/g, '<em>$1</em>');
    context.setText(text);
    return context;
  }
}
 
class MarkdownInterpreter {
  constructor() {
    this.rules = [];
  }
 
  addRule(rule) {
    this.rules.push(rule);
  }
 
  interpret(context) {
    for (const rule of this.rules) {
      rule.interpret(context);
    }
    return context.getText();
  }
}
 
const interpreter = new MarkdownInterpreter();
interpreter.addRule(new BoldInterpreter());
interpreter.addRule(new ItalicInterpreter());
 
const context = new InterpreterContext('這是 **粗體** 和 *斜體*');
const html = interpreter.interpret(context);
console.log(html);

優點

  • 語法規則清楚
  • 易於擴充新的語法

缺點

  • 規則複雜時類別暴增
  • 效能較低

延伸閱讀