酷愛生活、享受文娛、專注技術(shù),歡迎關(guān)注微信公眾號QGer,我們1起見證成長!
甚么是解釋器模式?
官方解釋:to define a representation of grammar of a given language, along with an interpreter that uses this representation to interpret sentences in the language。
定義1個給定語言的語法表達(dá)式,并用該表達(dá)式作為1個解釋器來解釋語言中的句子。
通俗解釋:給定1種語言及相干語法,根據(jù)這些語法定義1個語法表達(dá)式的解釋器,客戶端可使用這個解釋器來解釋這個語言中句子。
為何使用解釋器模式?
語法表達(dá)式進(jìn)行抽象封裝,易于修改及拓展,當(dāng)這個語言新增了某種特性,可以通過繼承抽象表達(dá)式類來實現(xiàn)新的語言特性。
每條語法都可以表示為1個表達(dá)式類,實現(xiàn)起來比較容易。
PS:該模式由于其結(jié)構(gòu)特性,對復(fù)雜語法很難保護(hù),履行效力比較低,因此實際開發(fā)中幾近不適用這個模式,但是其本身的結(jié)構(gòu)和思想還是可以學(xué)習(xí)鑒戒1下的。
如何使用解釋器模式?
UML圖以下:
各個組件解釋:
AbstractExpression(抽象表達(dá)式):聲明1個抽象的解釋操作interpreter,這個接口為所有具體表達(dá)式角色(抽象語法樹中的節(jié)點)都要實現(xiàn)的。
TerminalExpression(終結(jié)表達(dá)式):實現(xiàn)了抽象表達(dá)式角色所要求的接口,主要是1個interpret()方法;文法中的每個終結(jié)符都有1個具體終結(jié)表達(dá)式與之相對應(yīng)。比如有1個簡單的公式R=R1+R2,在里面R1和R2就是終結(jié)符,對應(yīng)的解析R1和R2的解釋器就是終結(jié)符表達(dá)式。
NonTerminalExpression(非終結(jié)表達(dá)式):文法中的每條規(guī)則都需要1個具體的非終結(jié)符表達(dá)式,非終結(jié)符表達(dá)式1般是文法中的運算符或其他關(guān)鍵字,比如公式R=R1+R2中,“+”就是非終結(jié)符,解析“+”的解釋器就是1個非終結(jié)符表達(dá)式。
Client(客戶端):使用解釋器的角色。
Context(上下文):這個角色的任務(wù)1般是用來寄存文法中各個終結(jié)符所對應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要寄存到環(huán)境角色中,很多情況下我們使用1個映照(Map)來充當(dāng)環(huán)境角色就足夠了。
利用實例:
有這么1個簡單的需求,給予1個字符,讓你判斷是不是是數(shù)字字符(‘0’-‘9’),可以這么實現(xiàn):
1、定義1個抽象表達(dá)式
interface AbstractExpression {
boolean interpret(Character character);
}
2、定義終結(jié)表達(dá)式,即直接判斷字符是不是是數(shù)字字符
public class TerminalExpression implements AbstractExpression {
@Override
public boolean interpret(Character character) {
//是不是是數(shù)字字符
return character.isDigit(character);
}
}
3、定義簡單的非終結(jié)表達(dá)式,and 、not 、or
public class AndExpression implements AbstractExpression {
private AbstractExpression leftExpression;
private AbstractExpression rightExpression;
public AndExpression(AbstractExpression leftExpression, AbstractExpression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public boolean interpret(Character character) {
return leftExpression.interpret(character) && rightExpression.interpret(character);
}
}
public class NotExpression implements AbstractExpression {
private AbstractExpression expression;
public NotExpression(AbstractExpression expression) {
this.expression = expression;
}
@Override
public boolean interpret(Character character) {
return !expression.interpret(character);
}
}
public class OrExpression implements AbstractExpression {
private AbstractExpression leftExpression;
private AbstractExpression rightExpression;
public OrExpression(AbstractExpression leftExpression, AbstractExpression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public boolean interpret(Character character) {
return leftExpression.interpret(character) || rightExpression.interpret(character);
}
}
4、客戶端使用,這里由于相對簡單,不需要使用context組件:
public class Client {
public static void main(String[] args) {
Character digitCharacter = new Character('1');
Character notdigitCharacter = new Character('l');
AbstractExpression terminalExpression = new TerminalExpression();
AbstractExpression notExpression = new NotExpression(terminalExpression);
AbstractExpression andExpression = new AndExpression(terminalExpression, notExpression);
AbstractExpression orExpression = new OrExpression(terminalExpression, notExpression);
System.out.println(andExpression.interpret(digitCharacter));
System.out.println(andExpression.interpret(notdigitCharacter));
System.out.println(orExpression.interpret(digitCharacter));
System.out.println(orExpression.interpret(notdigitCharacter));
}
}