天天看點

23種設計模式之_解釋器模式

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

類型:行為類模式

類圖:

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 stack = new Stack();
            for(int i=0;i
             //進行文法判斷,遞歸調用  
        }  
        Expression exp = stack.pop();  
        exp.interpreter(ctx);  
    }  
}      

文法遞歸的代碼部分需要根據具體的情況來實作,是以在代碼中沒有展現。抽象表達式是生成文法集合的關鍵,每個非終結符表達式解釋一個最小的文法單元,然後通過遞歸的方式将這些文法單元組合成完整的文法,這就是解釋器模式。

解釋器模式的優缺點

解釋器是一個簡單的文法分析工具,它最顯著的優點就是擴充性,修改文法規則隻需要修改相應的非終結符就可以了,若擴充文法,隻需要增加非終結符類就可以了。

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

解釋器模式的适用場景

繼續閱讀