解釋器模式

来源:https://www.cnblogs.com/weixk/archive/2020/06/18/13155626.html
-Advertisement-
Play Games

#一、解釋器模式介紹 ##1、定義與類型 定義:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。 為瞭解釋一種語言,而為語言創建的解釋器 類型:行為型 #2、適用場景 某個特定類型問題發生頻率足夠高 ##3、優點 語法由很多類表示,容易改變及擴展此“語 ...


一、解釋器模式介紹

1、定義與類型

定義:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
為瞭解釋一種語言,而為語言創建的解釋器
類型:行為型

2、適用場景

某個特定類型問題發生頻率足夠高

3、優點

語法由很多類表示,容易改變及擴展此“語言"

4、缺點

當語法規則數目太多時,增加了系統複雜度

5、相關設計模式

解釋器模式和適配器模式
適配器模式是需要預先知道要適配的規則,解釋器則是要把規則寫好,根據規則執行解釋

二、代碼示例

模擬場景:模擬電腦解釋計算表達式,例如中綴表達式 6 * (100 +11) ,電腦會先轉換為尾碼運算符 6 100 11 + * ,轉換過程此處省略,再依次入棧,遇到運算符則出棧中的兩個數字進行計算,再將計算結果入棧。
此處需要補充知識點:電腦如何計算我們的表達式的,可參考https://wenku.baidu.com/view/3ff189a15ef7ba0d4a733bb5.html中的表達式求值

解釋器介面:

public interface Interpreter {
    int interpret();
}

數字解釋器:

public class NumberInterpreter implements Interpreter {
    private int number;

    public NumberInterpreter(int number) {
        this.number = number;
    }

    public NumberInterpreter(String number) {
        this.number = Integer.valueOf(number);
    }

    @Override
    public int interpret() {
        return this.number;
    }
}

加法解釋器:

public class AddInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;

    public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() + this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "+";
    }
}

乘法解釋器:

public class MultiInterpreter implements Interpreter {
    private Interpreter firstExpression, secondExpression;

    public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() * this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "*";
    }
}

運算符工具類:

public class OperatorUtil {
    public static boolean isOperator(String symbol) {
        return (symbol.equals("+") || symbol.equals("*"));
    }

    public static Interpreter getExpressionObject(Interpreter firstExpression, Interpreter secondExpression, String symbol) {
        if (symbol.equals("+")) {
            return new AddInterpreter(firstExpression, secondExpression);
        } else if (symbol.equals("*")) {
            return new MultiInterpreter(firstExpression, secondExpression);
        }
        return null;
    }
}

轉換器類:

public class MyExpressionParser {
    private Stack<Interpreter> stack = new Stack<Interpreter>();

    public int parser(String str) {
        String[] strItemArray = str.split(" ");
        for (String symbol : strItemArray) {
            if (!OperatorUtil.isOperator(symbol)) {
                Interpreter numberExpression = new NumberInterpreter(symbol);
                stack.push(numberExpression);
                System.out.println(String.format("入棧:%d", numberExpression.interpret()));
            } else {
                // 是運算符,可以計算
                Interpreter firstExpression = stack.pop();
                Interpreter secondExpression = stack.pop();
                System.out.println(String.format("出棧:%d 和 %d", firstExpression.interpret(), secondExpression.interpret()));
                Interpreter operator = OperatorUtil.getExpressionObject(firstExpression, secondExpression, symbol);
                System.out.println(String.format("應用運算符:%s", operator));
                int result = operator.interpret();
                NumberInterpreter resultExpression = new NumberInterpreter(result);
                stack.push(resultExpression);
                System.out.println(String.format("階段結果入棧:%d", resultExpression.interpret()));
            }
        }
        int result = stack.pop().interpret();
        return result;
    }
}

測試類:

public class Test {
    public static void main(String[] args) {
        String inputStr = "6 100 11 + *";
        MyExpressionParser expressionParser = new MyExpressionParser();
        int result = expressionParser.parser(inputStr);
        System.out.println(result);
    }
}

輸出:
入棧:6
入棧:100
入棧:11
出棧:11 和 100
應用運算符:+
階段結果入棧:111
出棧:111 和 6
應用運算符:*
階段結果入棧:666
666

三、源碼示例

1、JDK中的正則Pattern

2、spring中的El表達式

測試:

public class SpringTest {
    public static void main(String[] args) {
        org.springframework.expression.ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("6 * (100 + 11)");
        int result = (Integer) expression.getValue();
        System.out.println(result);
    }
}

輸出:666


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

-Advertisement-
Play Games
更多相關文章
  • 前言 1.本文將從零開始手寫一份vue-next中的響應式原理,出於篇幅和理解的難易程度,我們將只實現核心的api並忽略一些邊界的功能點 本文將實現的api包括 track trigger effect reactive watch computed2.最近很多人私信我問前端問題,博客登陸的少沒及時 ...
  • multipage Github地址 github.com/qinouz/mult…基於 vue-cli4.0 構建 多頁面 模板腳手架! 啟動項目 git clone https://github.com/qinouz/multipage.git cd multipage npm install ...
  • 遇到問題 數據源有數據,但表體無法渲染出數據。 排查問題之路 其實關於layui表格無法渲染的問題之前也遇到過,我知道的情況以下幾種 數據源返回的的格式不正確 (code 必須為 0 ) 正確的返回格式:{"code":0,"msg":"","count":1000,"data":[]} 數據源正確 ...
  • 轉載請註明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 原文出處:https://dzone.com/articles/why-masses-are-not-using-latest-css-features-in-20 儘管CSS每年都會發佈全新的特性,但實際上 ...
  • 6.1 webpack概念的引入 在網頁中會引用哪些常見的靜態資源? JS .js、 .jsx 、.coffee、 .ts(TypeScript 類 C# 語言) CSS .css、 .less、 .sass 、.scss Images .jpg 、.png、 .gif 、.bmp 、.svg 字體 ...
  • 常用設計模式思維導圖,大部分設計模式在spring和jdk源碼中都有體現。 在學習spring源碼前,有必要花一定時間瞭解設計模式。 ...
  • 訪問者模式是一種較為複雜的行為型設計模式,它包含訪問者和被訪問元素兩個主要組成部分,這些被訪問的元素具有不同的類型,且不同的訪問者可以對其進行不同的訪問操作 模式動機 對於系統中某些對象,它們存儲在同一個集合中,且具有不同的類型。對於該集合中的對象,可以接受一類稱為訪問者的對象來訪問,不同的訪問者其 ...
  • 1.模型管理 :web線上流程設計器、預覽流程xml、導出xml、部署流程 2.流程管理 :導入導出流程資源文件、查看流程圖、根據流程實例反射出流程模型、激活掛起 3.運行中流程:查看流程信息、當前任務節點、當前流程圖、作廢暫停流程、指派待辦人 4.歷史的流程:查看流程信息、流程用時、流程狀態、查看 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...