描述
????解釋器模式是類的行為模式。給定一個語言之后,解釋器模式可以定義出其文法的一種表示,并同時提供一個解釋器。客戶端可以使用這個解釋器來解釋這個語言中的句子。
簡介

解釋器模式類圖
????給分析對象定義一個語言,并定義該語言的文法表示,再設(shè)計(jì)一個解析器來解釋語言中的句子。也就是說,用編譯語言的方式來分析應(yīng)用中的實(shí)例。這種模式實(shí)現(xiàn)了文法表達(dá)式處理的接口,該接口解釋一個特定的上下文。
角色
- 抽象表達(dá)式(Expression)角色:聲明一個所有的具體表達(dá)式角色都需要實(shí)現(xiàn)的抽象接口。這個接口主要是一個interpret()方法,稱做解釋操作。
- 終結(jié)符表達(dá)式(TerminalExpression)角色:是抽象表達(dá)式的子類,用來實(shí)現(xiàn)文法中與終結(jié)符相關(guān)的操作,文法中的每一個終結(jié)符都有一個具體終結(jié)表達(dá)式與之相對應(yīng)。
- 非終結(jié)符表達(dá)式(NonterminalExpression)角色:也是抽象表達(dá)式的子類,用來實(shí)現(xiàn)文法中與非終結(jié)符相關(guān)的操作,文法中的每條規(guī)則都對應(yīng)于一個非終結(jié)符表達(dá)式。
- 環(huán)境(Context)角色:通常包含各個解釋器需要的數(shù)據(jù)或是公共的功能,一般用來傳遞被所有解釋器共享的數(shù)據(jù),后面的解釋器可以從這里獲取這些值。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 擴(kuò)展性好:由于在解釋器模式中使用類來表示語言的文法規(guī)則,因此可以通過繼承等機(jī)制來改變或擴(kuò)展文法。
- 容易實(shí)現(xiàn) :在語法樹中的每個表達(dá)式節(jié)點(diǎn)類都是相似的,所以實(shí)現(xiàn)其文法較為容易。
缺點(diǎn)
- 執(zhí)行效率較低:解釋器模式中通常使用大量的循環(huán)和遞歸調(diào)用,當(dāng)要解釋的句子較復(fù)雜時,其運(yùn)行速度很慢,且代碼的調(diào)試過程也比較麻煩。
- 會引起類膨脹:解釋器模式中的每條規(guī)則至少需要定義一個類,當(dāng)包含的文法規(guī)則很多時,類的個數(shù)將急劇增加,導(dǎo)致系統(tǒng)難以管理與維護(hù)。
- 可應(yīng)用的場景比較少:在軟件開發(fā)中,需要定義語言文法的應(yīng)用實(shí)例非常少,所以這種模式很少被使用到。
使用場景
- 當(dāng)語言的文法較為簡單,且執(zhí)行效率不是關(guān)鍵問題時。
- 當(dāng)問題重復(fù)出現(xiàn),且可以用一種簡單的語言來進(jìn)行表達(dá)時。
- 當(dāng)一個語言需要解釋執(zhí)行,并且語言中的句子可以表示為一個抽象語法樹的時候,如 XML 文檔解釋。
示例
/**
* 環(huán)境角色
*/
public class Context {
private Map<Expression, Integer> map = new HashMap<Expression, Integer>();
public void add(Expression s, Integer value) {
map.put(s, value);
}
public int lookup(Expression s) {
return map.get(s);
}
}
/**
* 抽象表達(dá)式(Expression)角色
*/
public interface Expression {
int interpret(Context context);
}
/**
* 終結(jié)符表達(dá)式(TerminalExpression)角色
*/
public class TerminalExpression implements Expression {
private String variable;
public TerminalExpression(String variable) {
this.variable = variable;
}
@Override
public int interpret(Context context) {
return context.lookup(this);
}
}
/**
* 非終結(jié)符表達(dá)式(NonterminalExpression)角色
*/
public class MinusExpression implements Expression {
private Expression expression1;
private Expression expression2;
public MinusExpression(Expression expression1, Expression expression2) {
this.expression1 = expression1;
this.expression2 = expression2;
}
@Override
public int interpret(Context context) {
return this.expression1.interpret(context) - this.expression2.interpret(context);
}
}
/**
* 非終結(jié)符表達(dá)式(NonterminalExpression)角色
*/
public class AddExpression implements Expression {
private Expression expression1, expression2;
public AddExpression(Expression expression1, Expression expression2) {
this.expression1 = expression1;
this.expression2 = expression2;
}
@Override
public int interpret(Context context) {
return this.expression1.interpret(context) + this.expression2.interpret(context);
}
}
/**
* 客戶端角色
*/
public class Client {
public static void main(String[] args) {
Context context = new Context();
TerminalExpression a = new TerminalExpression("a");
TerminalExpression b = new TerminalExpression("b");
TerminalExpression c = new TerminalExpression("c");
context.add(a, 4);
context.add(b, 8);
context.add(c, 2);
System.out.println(new AddExpression(a, b).interpret(context));
System.out.println(new MinusExpression(b, c).interpret(context));
}
}

執(zhí)行結(jié)果圖