---
# System prepended metadata

title: 16. Interpreter
tags: [DesignPatterns]

---

# 16. Interpreter

###### tags: `DesignPatterns`

## 關於 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](https://en.wikipedia.org/wiki/Design_Patterns)

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

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

優點：
- 符合 單一職責原則(Single Responsibility Principle)
- 符合 開閉原則(Open Closed Principle)

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

---
## 2. UML
![](https://i.imgur.com/8QYGDc2.jpg)

Class 間關聯：
- Client 關聯 Context & AbstractExpression
- TerminalExpression & NonterminalExpression 繼承 AbstractExpression
- NonterminalExpression 可包含 AbstractExpression

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

---
## 3. 將 UML 轉為程式碼
由直譯器來處理的內容
```C#
/// <summary>
/// 由直譯器來處理的內容
/// </summary>
public class Context
{
}
```
直譯的抽象類別或介面
```C#
/// <summary>
/// 直譯的抽象類別或介面
/// </summary>
public abstract class AbstractExpression
{
    public abstract void Interpret(Context context);
}
```
直譯邏輯實作，已無接續項目，不再遞迴
```C#
/// <summary>
/// 直譯邏輯實作，已無接續項目，不再遞迴
/// </summary>
public class TerminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Terminal.Interpret()");
    }
}
```
直譯邏輯實作，有接續項目
```C#
/// <summary>
/// 直譯邏輯實作，有接續項目
/// </summary>
public class NonterminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Nonterminal.Interpret()");
    }
}
```
呼叫直譯器並傳入欲處理內容
```C#
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();
}
```
執行結果
```Console
Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()
```

---
## 完整程式碼
GitHub：[Behavioral_03_Interpreter](https://github.com/darionnnnnn/blog/tree/master/Blog/Behavioral_03_Interpreter)
   
---
## 總結
### Interpreter 網路上看到例子像是 [Regular Expression](https://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F)轉換、數字轉換之類的，都滿難想像如何套用至我們的日常開發中，會這樣覺得並不奇怪，因為 Interpreter 本來就屬於較少機會使用到的 Pattern，在複雜情境中還有效能問題，故本篇沒有附上情境範例。

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

---
## 參考資料
1. [Design Patterns](https://en.wikipedia.org/wiki/Design_Patterns)
2. [大話設計模式](https://www.tenlong.com.tw/products/9789866761799)
2. [dofactory](https://www.dofactory.com/)

---

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