16. Interpreter


Posted by WayneCheng on 2021-01-23

關於 Interpreter 本篇將討論以下幾個問題

1. 關於 Interpreter

2. UML

3. 將 UML 轉為程式碼


測試環境:

OS:Windows 10
IDE:Visual Studio 2019


1. 關於 Interpreter

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

by Gang of Four

  • 給定一種語言,直譯器為這語言的文法定義一種描述,使用描述來解釋語言中的句子

Interpreter(直譯器)屬於行為型(Behavioral Patterns),當遇到大量相同問題,且有特定的處理方式時,可以藉由 Interpreter 來將問題的處理方式集中管理,且有新處理方式時,只需要將新處理方式加入 Interpreter 即可。

優點:

  • 符合 單一職責原則(Single Responsibility Principle)
  • 符合 開閉原則(Open Closed Principle)

缺點:

  • 複雜的情境會產生大量的 class 造成整體程式複雜度提升
  • 遞迴方式呼叫再複雜的情境下可能會有效能的問題

2. UML

Class 間關聯:

  • Client 關聯 Context & AbstractExpression
  • TerminalExpression & NonterminalExpression 繼承 AbstractExpression
  • NonterminalExpression 可包含 AbstractExpression

Class:

  • Client:呼叫端
  • AbstractExpression:直譯的抽象類別或介面
  • TerminalExpression:直譯邏輯實作,已無接續項目,不再遞迴
  • NonterminalExpression:直譯邏輯實作,有接續項目
  • Context:由直譯器來處理的內容

3. 將 UML 轉為程式碼

由直譯器來處理的內容

/// <summary>
/// 由直譯器來處理的內容
/// </summary>
public class Context
{
}

直譯的抽象類別或介面

/// <summary>
/// 直譯的抽象類別或介面
/// </summary>
public abstract class AbstractExpression
{
    public abstract void Interpret(Context context);
}

直譯邏輯實作,已無接續項目,不再遞迴

/// <summary>
/// 直譯邏輯實作,已無接續項目,不再遞迴
/// </summary>
public class TerminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Terminal.Interpret()");
    }
}

直譯邏輯實作,有接續項目

/// <summary>
/// 直譯邏輯實作,有接續項目
/// </summary>
public class NonterminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Nonterminal.Interpret()");
    }
}

呼叫直譯器並傳入欲處理內容

static void Main(string[] args)
{
    Default.Context context = new Default.Context();

    ArrayList list = new ArrayList();

    list.Add(new Default.TerminalExpression());
    list.Add(new Default.NonterminalExpression());
    list.Add(new Default.TerminalExpression());
    list.Add(new Default.TerminalExpression());

    foreach (Default.AbstractExpression exp in list)
    {
        exp.Interpret(context);
    }

    Console.ReadLine();
}

執行結果

Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()

完整程式碼

GitHub:Behavioral_03_Interpreter


總結

Interpreter 網路上看到例子像是 Regular Expression轉換、數字轉換之類的,都滿難想像如何套用至我們的日常開發中,會這樣覺得並不奇怪,因為 Interpreter 本來就屬於較少機會使用到的 Pattern,在複雜情境中還有效能問題,故本篇沒有附上情境範例。

不過基本概念還是可以了解一下,真的遇到要使用時再詳細了解即可。


參考資料

  1. Design Patterns
  2. 大話設計模式
  3. dofactory

新手上路,若有錯誤還請告知,謝謝


#designpattern #CSharp







Related Posts

Cmder 更改 lambda λ 符號

Cmder 更改 lambda λ 符號

7. 濾波器設計

7. 濾波器設計

React 用 key 強迫 component 重新渲染

React 用 key 強迫 component 重新渲染


Comments