1、定義
解釋器模式(interpreter),給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語句中的句子。
2、解決的問題
如果一種特定類型的問題發生的頻率足夠高,那麼可能就值得將該問題的各個實例表述為一個簡單語句中的句子,這樣就可以構造一個解釋器,該解釋器通過解釋這些句子來解決該問題。 比方說,我們通常在字符串中搜索匹配的字符或判斷一個字符串是否符合我們規定的格式,我們會用到正則表達式,正則表達式就是解釋器模式的一種應用,解釋器為正則表達式定義了一個文法, 如何表示一個特定的正則表達式,以及如何解釋這個正則表達式。
3、UML
各個類說明:
抽象表達式角色(AbstractExpression): 聲明一個抽象的解釋操作,這個接口為所有具體表達式角色都要實現的.
終結符表達式角色(TerminalExpression): 實現與文法中的元素相關聯的解釋操作,通常一個解釋器模式中只有一個終結符表達式,但有多個實例對應不同的終結符.
終結符就是語言中用到的基本元素,一般不能再被分解,如: x -> xa, 這裡a是終結符,因為沒有別的規則可以把a變成別的符號,不過x可以變成別的符號,所以x是非終結符.
非終結符表達式角色(NonterminalExpression): 文法中的每條規則對應於一個非終結表達式, 非終結表達式根據邏輯的復雜程度而增加,原則上每個文法規則都對應一個非終結符表達式.
Context:包含解釋器之外的全局信息
4、應用場景
當一個語言需要解釋執行,並且你課將該語言中的句子表示為一個抽象語法樹時,可以使用解析器模式。
5、使用解析器模式的好處
用了解析器模式,就意味著可以很容易改變和擴展文法,因為該模式使用類來表示文法規則,我們可以使用繼承來改變或擴展文法。也比較容易實現文法,因為定義抽象語法樹中各個節點的類的實現大題類似,這些類都易於直接編寫。
6、不足
解析器模式為文法中的每一條規則至少定義了一個類,因此包含許多規則的文法可能難以管理和維護。建議當文法非常復雜是,使用其他的技術如語法分析程序或編譯器生成器來處理。
7、應用
正則表達式,浏覽器等。
8、demo
抽象表達式
package com.zcr.interpreter;
//抽象表達式
public abstract class AbstractExpression
{
public abstract void Interpret(Context contex);
}
非終端解析器
package com.zcr.interpreter;
public class NonterminalExpression extends AbstractExpression
{
@Override
public void Interpret(Context contex)
{
System.out.println("非終端解析器");
}
}
終端解析器
package com.zcr.interpreter;
//終端解析器
public class TerminalExpression extends AbstractExpression
{
@Override
public void Interpret(Context contex)
{
System.out.println("中斷解釋器");
}
}
package com.zcr.interpreter;
public class Context
{
private String input;
public String getInput()
{
return input;
}
public void setInput(String input)
{
this.input = input;
}
private String output;
public String getOutput()
{
return output;
}
public void setOutput(String output)
{
this.output = output;
}
}
主函數調用測試
package com.zcr.interpreter;
import java.util.ArrayList;
import java.util.List;
public class InterpreterTest
{
public static void main(String[] args)
{
Context context = new Context();
List<AbstractExpression> list = new ArrayList<AbstractExpression>();
list.add(new TerminalExpression());
list.add(new NonterminalExpression());
list.add(new TerminalExpression());
list.add(new TerminalExpression());
for(AbstractExpression exp : list)
{
exp.Interpret(context);
}
}
}
結果: