一、定義
解釋器模式(Interpreter Pattern)是一種按照規(guī)定語法進(jìn)行解析的方案,在現(xiàn)在項(xiàng)目中使 用較少,其定義如下:Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.(給定一門語言,定義 它的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來解釋語言中的句子。)
解釋器模式的通用類圖如圖所示。
- AbstractExpression——抽象解釋器
具體的解釋任務(wù)由各個(gè)實(shí)現(xiàn)類完成,具體的解釋器分別由TerminalExpression和Non-terminalExpression完成。
- TerminalExpression——終結(jié)符表達(dá)式
實(shí)現(xiàn)與文法中的元素相關(guān)聯(lián)的解釋操作,通常一個(gè)解釋器模式中只有一個(gè)終結(jié)符表達(dá) 式,但有多個(gè)實(shí)例,對(duì)應(yīng)不同的終結(jié)符。
- NonterminalExpression——非終結(jié)符表達(dá)式
文法中的每條規(guī)則對(duì)應(yīng)于一個(gè)非終結(jié)表達(dá)式,具體到我們的例子就是加減法規(guī)則分別對(duì)應(yīng)到AddExpression和SubExpression兩個(gè)類。非終結(jié)符表達(dá)式根據(jù)邏輯的復(fù)雜程度而增加,原則上每個(gè)文法規(guī)則都對(duì)應(yīng)一個(gè)非終結(jié)符表達(dá)式。
- Context——環(huán)境角色
//抽象表達(dá)式
public abstract class Expression {
//每個(gè)表達(dá)式必須有一個(gè)解析任務(wù)
public abstract Object interpreter(Context ctx);
}
//終結(jié)符表達(dá)式
public class TerminalExpression extends Expression {
//通常終結(jié)符表達(dá)式只有一個(gè),但是有多個(gè)對(duì)象
public Object interpreter(Context ctx) {
return null;
}
}
//非終結(jié)符表達(dá)式
public class NonterminalExpression extends Expression {
//每個(gè)非終結(jié)符表達(dá)式都會(huì)對(duì)其他表達(dá)式產(chǎn)生依賴
public NonterminalExpression(Expression... expression){ }
public Object interpreter(Context ctx) {
//進(jìn)行文法處理
return null;
}
}
//客戶類
public class Client {
public static void main(String[] args) {
Context ctx = new Context();
//通常定一個(gè)語法容器,容納一個(gè)具體的表達(dá)式,通常為L(zhǎng)istArray、LinkedList、Stack等類型
Stack&Expression> stack = null;
for(;;){
//進(jìn)行語法判斷,并產(chǎn)生遞歸調(diào)用
}
//產(chǎn)生一個(gè)完整的語法樹,由各個(gè)具體的語法分析進(jìn)行解析
Expression exp = stack.pop();
//具體元素進(jìn)入場(chǎng)景
exp.interpreter(ctx);
}
}
二、應(yīng)用
2.1 優(yōu)點(diǎn)
解釋器是一個(gè)簡(jiǎn)單語法分析工具,它最顯著的優(yōu)點(diǎn)就是擴(kuò)展性,修改語法規(guī)則只要修改 相應(yīng)的非終結(jié)符表達(dá)式就可以了,若擴(kuò)展語法,則只要增加非終結(jié)符類就可以了。
2.2 缺點(diǎn)
- 解釋器模式會(huì)引起類膨脹
每個(gè)語法都要產(chǎn)生一個(gè)非終結(jié)符表達(dá)式,語法規(guī)則比較復(fù)雜時(shí),就可能產(chǎn)生大量的類文 件,為維護(hù)帶來了非常多的麻煩。
- 解釋器模式采用遞歸調(diào)用方法
每個(gè)非終結(jié)符表達(dá)式只關(guān)心與自己有關(guān)的表達(dá)式,每個(gè)表達(dá)式需要知道最終的結(jié)果,必 須一層一層地剝繭,無論是面向過程的語言還是面向?qū)ο蟮恼Z言,遞歸都是在必要條件下使 用的,它導(dǎo)致調(diào)試非常復(fù)雜。想想看,如果要排查一個(gè)語法錯(cuò)誤,我們是不是要一個(gè)斷點(diǎn)一 個(gè)斷點(diǎn)地調(diào)試下去,直到最小的語法單元。
- 效率問題
解釋器模式由于使用了大量的循環(huán)和遞歸,效率是一個(gè)不容忽視的問題,特別是一用于 解析復(fù)雜、冗長(zhǎng)的語法時(shí),效率是難以忍受的。
2.3 場(chǎng)景
- 重復(fù)發(fā)生的問題可以使用解釋器模式
例如,多個(gè)應(yīng)用服務(wù)器,每天產(chǎn)生大量的日志,需要對(duì)日志文件進(jìn)行分析處理,由于各 個(gè)服務(wù)器的日志格式不同,但是數(shù)據(jù)要素是相同的,按照解釋器的說法就是終結(jié)符表達(dá)式都 是相同的,但是非終結(jié)符表達(dá)式就需要制定了。在這種情況下,可以通過程序來一勞永逸地 解決該問題。
- 一個(gè)簡(jiǎn)單語法需要解釋的場(chǎng)景