Java設計模式:解釋器模式

作者:網絡 | 發布時間:2020年10月30日 | 閱讀:863

定義:給定一(yī)種語言,定義他的文法的一(yī)種表示,并定義一(yī)個解釋器,該解釋器使用該表示來解釋語言中(zhōng)句子。

類型:行爲類模式

類圖:

interpreter-pattern

解釋器模式是一(yī)個比較少用的模式,本人之前也沒有用過這個模式。下(xià)面我(wǒ)們就來一(yī)起看一(yī)下(xià)解釋器模式。

解釋器模式的結構

  • 抽象解釋器:聲明一(yī)個所有具體(tǐ)表達式都要實現的抽象接口(或者抽象類),接口中(zhōng)主要是一(yī)個interpret()方法,稱爲解釋操作。具體(tǐ)解釋任務由它的各個實現類來完成,具體(tǐ)的解釋器分(fēn)别由終結符解釋器TerminalExpression和非終結符解釋器NonterminalExpression完成。

  • 終結符表達式:實現與文法中(zhōng)的元素相關聯的解釋操作,通常一(yī)個解釋器模式中(zhōng)隻有一(yī)個終結符表達式,但有多個實例,對應不同的終結符。終結符一(yī)半是文法中(zhōng)的運算單元,比如有一(yī)個簡單的公式R=R1+R2,在裏面R1和R2就是終結符,對應的解析R1和R2的解釋器就是終結符表達式。

  • 非終結符表達式:文法中(zhōng)的每條規則對應于一(yī)個非終結符表達式,非終結符表達式一(yī)般是文法中(zhōng)的運算符或者其他關鍵字,比如公式R=R1+R2中(zhōng),+就是非終結符,解析+的解釋器就是一(yī)個非終結符表達式。非終結符表達式根據邏輯的複雜(zá)程度而增加,原則上每個文法規則都對應一(yī)個非終結符表達式。

  • 環境角色:這個角色的任務一(yī)般是用來存放(fàng)文法中(zhōng)各個終結符所對應的具體(tǐ)值,比如R=R1+R2,我(wǒ)們給R1賦值100,給R2賦值200。這些信息需要存放(fàng)到環境角色中(zhōng),很多情況下(xià)我(wǒ)們使用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 stack = new Stack();
            for(int i=0;i
             //進行語法判斷,遞歸調用  
        }  
        Expression exp = stack.pop();  
        exp.interpreter(ctx);  
    }  
}

文法遞歸的代碼部分(fēn)需要根據具體(tǐ)的情況來實現,因此在代碼中(zhōng)沒有體(tǐ)現。抽象表達式是生(shēng)成語法集合的關鍵,每個非終結符表達式解釋一(yī)個最小(xiǎo)的語法單元,然後通過遞歸的方式将這些語法單元組合成完整的文法,這就是解釋器模式。

解釋器模式的優缺點

解釋器是一(yī)個簡單的語法分(fēn)析工(gōng)具,它最顯著的優點就是擴展性,修改語法規則隻需要修改相應的非終結符就可以了,若擴展語法,隻需要增加非終結符類就可以了。

但是,解釋器模式會引起類的膨脹,每個語法都需要産生(shēng)一(yī)個非終結符表達式,語法規則比較複雜(zá)時,就可能産生(shēng)大(dà)量的類文件,爲維護帶來非常多的麻煩。同時,由于采用遞歸調用方法,每個非終結符表達式隻關心與自己相關的表達式,每個表達式需要知(zhī)道最終的結果,必須通過遞歸方式,無論是面向對象的語言還是面向過程的語言,遞歸都是一(yī)個不推薦的方式。由于使用了大(dà)量的循環和遞歸,效率是一(yī)個不容忽視的問題。特别是用于解釋一(yī)個解析複雜(zá)、冗長的語法時,效率是難以忍受的。

解釋器模式的适用場景

在以下(xià)情況下(xià)可以使用解釋器模式:

  • 有一(yī)個簡單的語法規則,比如一(yī)個sql語句,如果我(wǒ)們需要根據sql語句進行rm轉換,就可以使用解釋器模式來對語句進行解釋。

  • 一(yī)些重複發生(shēng)的問題,比如加減乘除四則運算,但是公式每次都不同,有時是a+b-cd,有時是ab+c-d,等等等等個,公式千變萬化,但是都是由加減乘除四個非終結符來連接的,這時我(wǒ)們就可以使用解釋器模式。

注意事項

解釋器模式真的是一(yī)個比較少用的模式,因爲對它的維護實在是太麻煩了,想象一(yī)下(xià),一(yī)坨一(yī)坨的非終結符解釋器,假如不是事先對文法的規則了如指掌,或者是文法特别簡單,則很難讀懂它的邏輯。解釋器模式在實際的系統開(kāi)發中(zhōng)使用的很少,因爲他會引起效率、性能以及維護等問題。

相關内容