解釋器模式

描述

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

簡介

解釋器模式類圖

????給分析對象定義一個語言,并定義該語言的文法表示,再設(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é)果圖
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容