23種設計模式之直譯器模式
定義:給定一種語言,定義他的文法的一種表示,並定義一個直譯器,該直譯器使用該表示來解釋語言中句子。
型別:行為類模式
類圖:
直譯器模式是一個比較少用的模式,本人之前也沒有用過這個模式。下面我們就來一起看一下直譯器模式。
直譯器模式的結構
- 抽象直譯器:宣告一個所有具體表示式都要實現的抽象介面(或者抽象類),介面中主要是一個interpret()方法,稱為解釋操作。具體解釋任務由它的各個實現類來完成,具體的直譯器分別由終結符直譯器TerminalExpression和非終結符直譯器NonterminalExpression完成。
- 終結符表示式:實現與文法中的元素相關聯的解釋操作,通常一個直譯器模式中只有一個終結符表示式,但有多個例項,對應不同的終結符。終結符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符,對應的解析R1和R2的直譯器就是終結符表示式。
- 非終結符表示式:文法中的每條規則對應於一個非終結符表示式,非終結符表示式一般是文法中的運算子或者其他關鍵字,比如公式R=R1+R2中,+就是非終結符,解析+的直譯器就是一個非終結符表示式。非終結符表示式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符表示式。
- 環境角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些資訊需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了。
程式碼實現
class Context {} abstract class Expression { public abstract Object interpreter(Context ctx); } class TerminalExpression extends Expression { public Object interpreter(Context ctx){ return null; } } class NonterminalExpression extends Expression { public NonterminalExpression(Expression...expressions){ } public Object interpreter(Context ctx){ return null; } } public class Client { public static void main(String[] args){ String expression = ""; char[] charArray = expression.toCharArray(); Context ctx = new Context(); Stack<Expression> stack = new Stack<Expression>(); for(int i=0;i<charArray.length;i++){ //進行語法判斷,遞迴呼叫 } Expression exp = stack.pop(); exp.interpreter(ctx); } }
文法遞迴的程式碼部分需要根據具體的情況來實現,因此在程式碼中沒有體現。抽象表示式是生成語法集合的關鍵,每個非終結符表示式解釋一個最小的語法單元,然後通過遞迴的方式將這些語法單元組合成完整的文法,這就是直譯器模式。
直譯器模式的優缺點
直譯器是一個簡單的語法分析工具,它最顯著的優點就是擴充套件性,修改語法規則只需要修改相應的非終結符就可以了,若擴充套件語法,只需要增加非終結符類就可以了。
但是,直譯器模式會引起類的膨脹,每個語法都需要產生一個非終結符表示式,語法規則比較複雜時,就可能產生大量的類檔案,為維護帶來非常多的麻煩。同時,由於採用遞迴呼叫方法,每個非終結符表示式只關心與自己相關的表示式,每個表示式需要知道最終的結果,必須通過遞迴方式,無論是物件導向的語言還是程式導向的語言,遞迴都是一個不推薦的方式。由於使用了大量的迴圈和遞迴,效率是一個不容忽視的問題。特別是用於解釋一個解析複雜、冗長的語法時,效率是難以忍受的。
直譯器模式的適用場景
在以下情況下可以使用直譯器模式:
- 有一個簡單的語法規則,比如一個sql語句,如果我們需要根據sql語句進行rm轉換,就可以使用直譯器模式來對語句進行解釋。
- 一些重複發生的問題,比如加減乘除四則運算,但是公式每次都不同,有時是a+b-c*d,有時是a*b+c-d,等等等等個,公式千變萬化,但是都是由加減乘除四個非終結符來連線的,這時我們就可以使用直譯器模式。
注意事項
直譯器模式真的是一個比較少用的模式,因為對它的維護實在是太麻煩了,想象一下,一坨一坨的非終結符直譯器,假如不是事先對文法的規則瞭如指掌,或者是文法特別簡單,則很難讀懂它的邏輯。直譯器模式在實際的系統開發中使用的很少,因為他會引起效率、效能以及維護等問題。
相關文章
- 設計模式之直譯器模式設計模式
- 折騰Java設計模式之直譯器模式Java設計模式
- 20.java設計模式之直譯器模式Java設計模式
- 軟體設計模式系列之十七——直譯器模式設計模式
- 23種設計模式之組合模式設計模式
- 簡說設計模式——直譯器模式設計模式
- 極簡設計模式-直譯器模式設計模式
- 設計模式--直譯器模式和狀態模式設計模式
- 設計模式(十五)直譯器設計模式
- 23種設計模式之介面卡模式設計模式
- 23種設計模式之——動態代理模式設計模式
- 23種設計模式(三)--裝飾器模式設計模式
- 23天設計模式之迭代器模式設計模式
- 淺談23種設計模式之單例設計模式設計模式單例
- 23種設計模式之模板方法設計模式
- 畫江湖之23種設計模式設計模式
- 23種設計模式之代理模式(靜態代理)設計模式
- 23種設計模式設計模式
- 23種設計模式(八)-原型設計模式設計模式原型
- 23種設計模式(二)---策略設計模式設計模式
- 23種設計模式(四)-代理模式設計模式
- 【重溫23種設計模式】之工廠方法模式設計模式
- 23種設計模式之抽象工廠設計模式抽象
- Rust語言之GoF設計模式: 直譯器Interpreter模式RustGo設計模式
- 直譯器設計模式知識概括設計模式
- 23種設計模式(七)-狀態設計模式設計模式
- 23種設計模式(四)- 模板方法設計模式設計模式
- 23種設計模式-原型模式(3)設計模式原型
- 【23種設計模式】外觀模式(十)設計模式
- 23種設計模式:03裝飾模式設計模式
- 23種設計模式(抽象工廠模式)設計模式抽象
- 23種設計模式(六)單一職責之橋模式設計模式
- 23種設計模式(十二)介面隔離之門面模式設計模式
- 23天設計模式之代理模式設計模式
- PHP設計模式(二十二)—直譯器模式(Interpreter PattPHP設計模式
- 23種設計模式(六)-責任鏈設計模式設計模式
- GOF23--23種設計模式(一)Go設計模式
- 23種設計模式簡介設計模式