口译员设计模式示例
本文是我們名為“ Java設計模式 ”的學院課程的一部分。
在本課程中,您將深入研究大量的設計模式,并了解如何在Java中實現和利用它們。 您將了解模式如此重要的原因,并了解何時以及如何應用模式中的每一個。 在這里查看 !
目錄
1.簡介 2.什么是口譯員設計模式 3.實施口譯員設計模式 4.何時使用口譯員設計模式 5. JDK中的解釋器設計模式 6.下載源代碼1.簡介
口譯員設計模式是一種重型模式。 這一切都是關于通過創建針對自己的編程語言的解釋器來組合自己的編程語言,或處理現有的編程語言。 要使用這種模式,您必須對正規語法有一定的了解,才能將一種語言組合在一起。 可以想象,這是開發人員每天都不會真正使用的模式之一,因為創建自己的語言并不是很多人要做的事情。
例如,就形式語法而言,以新語言定義表達式可能類似于以下代碼片段:
expression ::= <command> | <repetition> | <sequence>
那么,使用新語言的每個表達式可能由命令,命令的重復和序列表達式組成。 每個項目都可以使用解釋方法表示為一個對象,以將您的新語言翻譯成可以在Java中運行的語言。
為了說明解釋器設計模式的用法,我們創建一個示例來解決簡單的數學表達式,但在此之前,讓我們在下面的部分中討論有關解釋器設計模式的一些詳細信息。
2.什么是口譯員設計模式
給定一種語言,請定義其語法的表示形式,以及使用該表示形式來解釋該語言句子的解釋器。
通常,語言由一組語法規則組成。 遵循這些語法規則可以構建不同的句子。 有時應用程序可能需要處理重復出現的相似請求,這些請求是一組語法規則的組合。 這些請求是不同的,但從某種意義上來說它們是相似的,因為它們都是使用同一組規則構成的。
一個簡單的例子就是提交給計算器程序的一組不同的算術表達式。 盡管每個這樣的表達式都不同,但是它們都是使用構成算術表達式語言語法的基本規則構造的。
在這種情況下,代替將每個不同的規則組合視為一個單獨的案例,對應用程序來說,具有解釋規則的通用組合的能力可能是有益的。 解釋器模式可用于在應用程序中設計此功能,以便其他應用程序和用戶可以使用由一組語法規則定義的簡單語言來指定操作。
可以將類層次結構設計為表示語法規則集,而層次結構中的每個類都表示一個單獨的語法規則。 可以將解釋器模塊設計為解釋使用上面設計的類層次結構構造的句子,并執行必要的操作。
由于每個語法規則都代表一個不同的類別,因此類別的數量會隨著語法規則的數量而增加。 具有廣泛而復雜的語法規則的語言需要大量的類。 語法簡單時,解釋器模式最有效。 具有簡單的語法避免了需要具有許多與所涉及的復雜規則集相對應的類,而這些類很難管理和維護。
圖1-類圖
抽象表達
- 聲明抽象語法樹中所有節點共有的抽象Interpret操作。
終端表達
- 實現與語法中的終端符號關聯的Interpret操作。
- 句子中每個終端符號都需要一個實例。
非末端表達
- 語法中的每個規則R ::= R1 R2 ... Rn都需要一個這樣的類。
- 為每個符號R1到Rn維護類型AbstractExpression實例變量。
- 為語法中的非終結符實現Interpret操作。 Interpret通常對表示R1到Rn的變量進行遞歸調用。
語境
- 包含解釋器的全局信息。
客戶
- 構建(或給定)抽象語法樹,該語法樹以語法定義的語言表示特定的句子。 抽象語法樹是根據NonterminalExpression和TerminalExpression類的實例組裝而成的。
- 調用Interpret操作。
3.實施口譯員設計模式
package com.javacodegeeks.patterns.interpreterpattern;public interface Expression {public int interpret(); }所有不同的具體表達式都使用上面的接口,并且覆蓋了解釋方法以定義它們在表達式上的特定操作。
以下是特定于操作的表達式類。
package com.javacodegeeks.patterns.interpreterpattern;public class Add implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Add(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() + rightExpression.interpret();}}package com.javacodegeeks.patterns.interpreterpattern;public class Product implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Product(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() * rightExpression.interpret();} }package com.javacodegeeks.patterns.interpreterpattern;public class Substract implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Substract(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() - rightExpression.interpret();}}package com.javacodegeeks.patterns.interpreterpattern;public class Number implements Expression{private final int n;public Number(int n){this.n = n;}@Overridepublic int interpret() {return n;}}下面是可選的實用程序類,其中包含用于執行表達式的不同實用程序方法。
package com.javacodegeeks.patterns.interpreterpattern;public class ExpressionUtils {public static boolean isOperator(String s) {if (s.equals("+") || s.equals("-") || s.equals("*"))return true;elsereturn false;}public static Expression getOperator(String s, Expression left, Expression right) {switch (s) {case "+":return new Add(left, right);case "-":return new Substract(left, right);case "*":return new Product(left, right);}return null;}}現在,讓我們測試示例。
package com.javacodegeeks.patterns.interpreterpattern;import java.util.Stack;public class TestInterpreterPattern {public static void main(String[] args) {String tokenString = "7 3 - 2 1 + *";Stack<Expression> stack = new Stack<>();String[] tokenArray = tokenString.split(" ");for (String s : tokenArray) {if (ExpressionUtils.isOperator(s)) {Expression rightExpression = stack.pop();Expression leftExpression = stack.pop();Expression operator = ExpressionUtils.getOperator(s, leftExpression,rightExpression);int result = operator.interpret();stack.push(new Number(result));} else {Expression i = new Number(Integer.parseInt(s));stack.push(i);}}System.out.println("( "+tokenString+" ): "+stack.pop().interpret());}}上面的代碼將提供以下輸出:
( 7 3 - 2 1 + * ): 12
請注意,我們已使用后綴表達式來解決它。
如果您不了解后綴,則這里有一個簡短的介紹。 數學表達式有三種表示法,即中綴,后綴和前綴。
- 前綴表示法是常用的算術和邏輯公式表示法,其中運算符在它們所作用的操作數之間(例如3+4以infix樣式編寫。
- 后綴也稱為反向波蘭表示法(RPN)是一種數學表示法,其中每個運算符都遵循其所有操作數,例如34+ 。
- 前綴 (波蘭表示法)是一種用于邏輯,算術和代數的表示法,其中運算符位于其操作數的左側,例如+34 。
Infix表示法通常在數學表達式中使用。 編程語言的解釋程序將其他兩個符號用作數學表達式的語法。
在上面的類中,我們在tokenString變量中聲明了表達式的后綴。 然后,我們拆分tokenString并將其分配到一個數組tokenArray 。 在逐個迭代令牌時,首先我們檢查了令牌是運算符還是操作數。 如果令牌是操作數,則將其推入堆棧,但如果是運算符,則從堆棧中彈出前兩個操作數。 ExpressionUtils的getOperation方法根據傳遞給它的運算符返回適當的表達式類。
然后,我們解釋結果并將其推回堆棧。 迭代完整的tokenList我們得到了最終結果。
4.何時使用口譯員設計模式
有一種要解釋的語言時,請使用解釋器模式,并且可以將語言中的語句表示為抽象語法樹。 解釋器模式在以下情況下效果最佳
- 語法很簡單。 對于復雜的語法,語法的類層次結構會變得龐大且難以管理。 在這種情況下,解析器生成器之類的工具是更好的選擇。 他們可以在不構建抽象語法樹的情況下解釋表達式,這可以節省空間并可能節省時間。
- 效率不是關鍵問題。 通常,最有效的解釋器不是通過直接解釋解析樹來實現的,而是先將其轉換為另一種形式。 例如,正則表達式通常被轉換為狀態機。 但是即使那樣,翻譯器也可以通過Interpreter模式實現,因此該模式仍然適用。
5. JDK中的解釋器設計模式
- java.util.Pattern
- java.text.Normalizer
- java.text.Format
6.下載源代碼
這是關于口譯員設計模式的課程。 您可以在此處下載源代碼: InterpreterPattern-Project
翻譯自: https://www.javacodegeeks.com/2015/09/interpreter-design-pattern.html
總結
- 上一篇: EAI的Spring集成教程
- 下一篇: cobertura 使用_使用Cober