Interpreter Pattern

来源:https://www.cnblogs.com/mysticbinary/archive/2023/09/08/17686606.html
-Advertisement-
Play Games

# It can explain what ? 如下是解釋器要解釋的主體: - 加減乘除等運算,3+4/9+6*8 - 摩爾斯電碼 - 正則表達式 - El表達式 - OGNL表達式 - 小明是北京人 - 小紅是一名售貨員 - 部門領導下發一則通知 - ... # How explain ? 解釋器 ...


It can explain what ?

如下是解釋器要解釋的主體:

  • 加減乘除等運算,3+4/9+6*8
  • 摩爾斯電碼
  • 正則表達式
  • El表達式
  • OGNL表達式
  • 小明是北京人
  • 小紅是一名售貨員
  • 部門領導下發一則通知
  • ...

How explain ?

解釋器模式常用於對簡單語言集的編譯或分析,例如:

  • 我是大學生
  • 張強學習編程
  • 小明是北京人
  • 部門領導下發一則通知

為了掌握好它的結構與實現,需要先瞭解編譯原理中的文法句子語法樹等相關概念。(其實不瞭解也行,可以直接看code,在回來看)

這裡提到的文法和句子的概念同編譯原理中的描述相同,

  • 文法指語言的語法規則
    如何解釋語言的規則
  • 句子是語言集中的元素
    例如,漢語中的句子有很多,“我是大學生”是其中的一個句子,可以用一棵語法樹來直觀地描述語言中的句子。

Grammar Concept

這個是分析的關鍵。

〈句子〉::=〈主語〉〈謂語〉〈賓語〉
〈主語〉::=〈代詞〉|〈名詞〉
〈謂語〉::=〈動詞〉
〈賓語〉::=〈代詞〉|〈名詞〉
〈代詞〉::= 你 | 我 | 他
〈名詞〉::= 大學生 | 小明 | 英語 | 張強
〈動詞〉::= 是 | 學習

註意:

  • ::= 表示“定義為”的意思;
  • 括住的是非終結符沒有括住的是終結符;
  • | 是 邏輯符號or.

Sentence

句子是語言的基本單位,是語言集中的一個元素,它由終結符構成,能由"文法"推導出
例如,上述文法可以推出“我是大學生”,所以它是句子。

Syntax Tree

語法樹是句子結構的一種樹型表示,它代表了句子的推導結果,它有利於理解句子語法結構的層次。

“我是大學生”的語法樹如圖所示:

<expression> ::= <代詞>是<名詞>
<代詞> ::= 我 | 你 | 他 | 她
<名詞> ::= 大學生 | 程式員 | 牲口 | 懦夫

終結符和非終結符

終結符表達式(Terminal Expression):
就是一個最終的元素,不可在向下分割。

非終結符表達式(Nonterminal Expression):
非終結符需要依照文法規則去分割,文法中的每條規則都對應於一個非終結符表達式。

Key Elements

解釋器模式包含以下主要角色。

  • 抽象表達式(Abstract Expression)角色:定義解釋器的介面,約定解釋器的解釋操作,主要包含解釋方法 interpret()。
  • 終結符表達式(Terminal Expression)角色:是抽象表達式的子類,用來實現文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結表達式與之相對應。
  • 非終結符表達式(Nonterminal Expression)角色:也是抽象表達式的子類,用來實現文法中與非終結符相關的操作,文法中的每條規則都對應於一個非終結符表達式。
  • 環境(Context)角色:通常包含各個解釋器需要的數據或是公共的功能,一般用來傳遞被所有解釋器共用的數據,後面的解釋器可以從這裡獲取這些值。
  • 客戶端(Client):主要任務是將需要分析的句子或表達式轉換成使用解釋器對象描述的抽象語法樹,然後調用解釋器的解釋方法,當然也可以通過環境角色間接訪問解釋器的解釋方法。

Example —— 公交車身份識別系統

需求描述:每個人坐車都需要繳費,每個人上車後需要刷自己的公交卡卡,每個人的卡裡都有每個人的信息,信息如下:

  • "韶關的老人";
  • "韶關的年輕人";
  • "廣州的婦女";
  • "廣州的兒童";
  • "山東的兒童";

你需要寫一個解釋器去識別每個人的身份,如果是“韶關”或者“廣州”的“老人” “婦女”“兒童”就可以免費乘車,其他人員乘車一次扣 2 元。

分析:本實例用“解釋器模式”設計比較適合,首先設計其文法規則如下:

<expression> ::= <city>的<person>
<city> ::= 韶關 | 廣州
<person> ::= 老人 | 婦女 | 兒童

Client

public static void main(String[] args){
      Context bus=new Context();
      bus.freeRide("韶關的老人");
      bus.freeRide("韶關的年輕人");
      bus.freeRide("廣州的婦女");
      bus.freeRide("廣州的兒童");
      bus.freeRide("山東的兒童");
}

Context

class Context {
    private String[] citys = {"韶關", "廣州"};
    private String[] persons = {"老人", "婦女", "兒童"};
    private Expression cityPerson;

    public Context() {
        Expression city = new TerminalExpression(citys);
        Expression person = new TerminalExpression(persons);
        cityPerson = new AndExpression(city, person);
    }

    public void freeRide(String info) {
        boolean ok = cityPerson.interpret(info);
        if (ok) System.out.println("您是" + info + ",您本次乘車免費!");
        else System.out.println(info + ",您不是免費人員,本次乘車扣費2元!");
    }
}
//抽象表達式類
interface Expression {
    public boolean interpret(String info);
}

//終結符表達式類
class TerminalExpression implements Expression {
    private Set<String> set = new HashSet<String>();

    public TerminalExpression(String[] data) {
        for (int i = 0; i < data.length; i++) set.add(data[i]);
    }

    public boolean interpret(String info) {
        if (set.contains(info))
            return true;
        return false;
    }
}

//非終結符表達式類
class AndExpression implements Expression {
    private Expression city = null;
    private Expression person = null;

    public AndExpression(Expression city, Expression person) {
        this.city = city;
        this.person = person;
    }

    public boolean interpret(String info) {
        String s[] = info.split("的");
        System.out.println(city.interpret(s[0]) && person.interpret(s[1]));
        return city.interpret(s[0]) && person.interpret(s[1]);
    }
}

out:

true
您是韶關的老人,您本次乘車免費!
false
韶關的年輕人,您不是免費人員,本次乘車扣費2元!
true
您是廣州的婦女,您本次乘車免費!
true
您是廣州的兒童,您本次乘車免費!
false
山東的兒童,您不是免費人員,本次乘車扣費2元!

Reference

設計模式之解釋器模式(Interpreter)詳解及代碼示例
https://www.cnblogs.com/jing99/p/12610089.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ### 前言 上篇文章 [13分鐘聊聊併發包中常用同步組件並手寫一個自定義同步組件](https://juejin.cn/post/7274475842998042665) 聊到併發包中常用的同步組件,並且還手把手實現了自定義的同步組件 本篇文章來聊聊併發包下的另一個核心-線程池 閱讀本文大概12分 ...
  • # Python初步瞭解裝飾器 - 裝飾器的概念 - 裝飾器的簡單使用 - 裝飾器的進階 - 裝飾器的練習 - 裝飾器的固定模塊 - 裝飾器的語法糖 ## 裝飾器的概念 ```python 裝飾器它不是一個新的知識點,它是有之前我們學習的名稱空間、函數嵌套、閉包函數等知識點彙總而來 器:工具 裝飾: ...
  • 在軟體開發中,我們經常會遇到這樣的情況:我們需要使用一個現有的類或者介面,但它與我們系統的目標介面不相容,而我們又不能修改它。這時候,我們該怎麼辦呢?大多數情況下我們都可以使用適配器模式來解決這個問題,**本文將從以下四個方面講解適配器模式**。 - 簡介 - 優缺點 - 應用場景 - Java 代 ...
  • ## 1. 什麼是Http2.0 HTTP/2.0,通常簡稱為HTTP/2,是一種用於傳輸超文本(例如網頁和資源文件)的網路協議。它是HTTP/1.1的繼任者,旨在提高性能和效率,以適應現代Web應用的需求。HTTP/2的主要特點包括以下幾點: 1. **多路復用(Multiplexing)**:H ...
  • 光看訪客這個名字,猜測這個訪客模式應該非常好理解,只要玩過Linux的人,都能深刻明白Root和非Root和訪客賬號登錄的巨大差別性。 # What is Visitor? 如果你沒玩過Linux,那麼假設公共的圖書館有一臺電腦,有兩個賬戶: - 其中一個是**管理員(Admin)**的賬戶,擁有這 ...
  • 作者:是奉壹呀 \ 來源:juejin.cn/post/7262274383287500860 看到一個評論,裡面提到了list.sort()和list.strem().sorted()排序的差異。 說到list sort()排序比stream().sorted()排序性能更好,但沒說到為什麼。 ! ...
  • Sermant是基於Java位元組碼增強技術的無代理服務網格,其利用Java位元組碼增強技術為宿主應用程式提供服務治理功能。 ...
  • 京東茅臺搶購腳本可以分為以下幾部分,具體實現步驟如下: 登錄京東賬號 首先需要登錄京東賬號。一個簡單的方式是使用Python的 selenium 庫。在使用 selenium 庫前,需要安裝 selenium 庫和對應的瀏覽器驅動。 示例代碼如下所示: from selenium import we ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...