您好,登錄后才能下訂單哦!
本篇文章為大家展示了Android中怎么實(shí)現(xiàn)解釋器模式,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
一、介紹
解釋器模式(Interpreter Pattern)是一種用的比較少的行為型模式,其提供了一種解釋語言的語法或表達(dá)式的方式,該模式定義了一個表達(dá)式接口,通過該接口解釋一個特定的上下文。在這么多的設(shè)計模式中,解釋器模式在實(shí)際運(yùn)用上相對來說要少很多,因?yàn)槲覀兒苌贂约喝?gòu)造一個語言的文法。雖然如此,既然它能夠在設(shè)計模式中有一席之位,那么必定有它的可用之處。
二、定義
給定一個語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。(其中語言就是我們需要解釋的對象,文法就是這個語言的規(guī)律,解釋器就是翻譯機(jī),通過文法來翻譯語言。)
三、使用場景
如果某個簡單的語言需要解釋執(zhí)行而且可以將該語言中的語句表示為一個抽象的語法樹時可以考慮使用解釋器模式。
在某些特定的領(lǐng)域出現(xiàn)不斷重復(fù)的問題時,可以將該領(lǐng)域的問題轉(zhuǎn)化為一種語法規(guī)則下的語句,然后構(gòu)建解釋器來解釋該語句。
四、解釋器模式的UML類圖
UML類圖:
角色介紹:
AbstractExpression:抽象表達(dá)式,聲明一個抽象的解釋操作父類,并定義一個抽象的 interpret() 解釋方法,其具體的實(shí)現(xiàn)在各個具體的子類解釋器中完成。
TerminalExpression:終結(jié)符表達(dá)式,實(shí)現(xiàn)了抽象表達(dá)式角色所要求的接口,主要是一個interpret()方法;文法中的每一個終結(jié)符都有一個具體終結(jié)表達(dá)式與之相對應(yīng)。比如有一個簡單的公式R=R1+R2,在里面R1和R2就是終結(jié)符,對應(yīng)的解析R1和R2的解釋器就是終結(jié)符表達(dá)式。
NonterminalExpression:非終結(jié)符表達(dá)式,文法中的每一條規(guī)則都需要一個具體的非終結(jié)符表達(dá)式,非終結(jié)符表達(dá)式一般是文法中的運(yùn)算符或者其他關(guān)鍵字,比如公式R=R1+R2中,“+”就是非終結(jié)符,解析“+”的解釋器就是一個非終結(jié)符表達(dá)式。
Context:上下文環(huán)境類,這個角色的任務(wù)一般是用來存放文法中各個終結(jié)符所對應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環(huán)境角色中,很多情況下我們使用Map來充當(dāng)環(huán)境角色就足夠了。
Client:客戶類,解析表達(dá)式,構(gòu)建抽象語法樹,執(zhí)行具體的解釋操作等。
通用代碼如下:
/** * 抽象表達(dá)式 */ public abstract class AbstractExpression { /** * 抽象的解析方法 * @param context 上下文環(huán)境對象 */ public abstract void interpret(Context context); } /** * 終結(jié)符表達(dá)式 */ public class TerminalExpression extends AbstractExpression{ @Override public void interpret(Context context) { //實(shí)現(xiàn)文法中與終結(jié)符有關(guān)的解釋操作 } } /** * 非終結(jié)符表達(dá)式 */ public class NonterminalExpression extends AbstractExpression{ @Override public void interpret(Context context) { //實(shí)現(xiàn)文法中與非終結(jié)符有關(guān)的解釋操作 } } /** * 上下文環(huán)境類 */ public class Context { } /** * 客戶類 */ public class Client { public static void main(String[] args) { //根據(jù)文法對特定句子構(gòu)建抽象語法樹后解釋 } }
五、簡單實(shí)現(xiàn)
我們使用解釋器模式對“m+n+p”這個表達(dá)式進(jìn)行解釋,那么代表數(shù)字的m、n和p就可以看成終結(jié)符號,而“+”這個運(yùn)算符號可以當(dāng)做非終結(jié)符號。
抽象的算數(shù)運(yùn)算解釋器:
public abstract class ArithemticExpression { /** * 抽象的解析方法 * 具體的解析邏輯由具體的子類實(shí)現(xiàn) * * @return 解析得到具體的值 */ public abstract int interpreter(); }
數(shù)字解釋器:
public class NumExpression extends ArithemticExpression{ private int num; public NumExpression(int num){ this.num = num; } @Override public int interpreter() { return num; } }
運(yùn)算符號解釋器:
public abstract class OperatorExpression extends ArithemticExpression{ protected ArithemticExpression exp1, exp2; public OperatorExpression(ArithemticExpression exp1, ArithemticExpression exp2){ this.exp1 = exp1; this.exp2 = exp2; } }
具體的加法運(yùn)算符解釋器:
public class AdditionExpression extends OperatorExpression{ public AdditionExpression(ArithemticExpression exp1, ArithemticExpression exp2) { super(exp1, exp2); } @Override public int interpreter() { return exp1.interpreter() + exp2.interpreter(); } }
處理解釋器:
public class Calculator { //聲明一個Stack棧儲存并操作所有相關(guān)的解釋器 private Stack<ArithemticExpression> mExpStack = new Stack<ArithemticExpression>(); public Calculator(String expression){ //聲明兩個ArithemticExpression類型的臨時變量,儲存運(yùn)算符左右兩邊的數(shù)字解釋器 ArithemticExpression exp1,exp2; //根據(jù)空格分割表達(dá)式字符串(比如1 + 2 + 3 + 4) String[] elements = expression.split(" "); /* * 遍歷表達(dá)式元素數(shù)組 */ for(int i = 0; i < elements.length; i++){ /* * 判斷運(yùn)算符號 */ switch (elements[i].charAt(0)) { case '+': //如果是加號,則將棧中的解釋器彈出作為運(yùn)算符號左邊的解釋器 exp1 = mExpStack.pop(); //同時將運(yùn)算符號數(shù)組下標(biāo)的下一個元素構(gòu)造為一個數(shù)字解釋器 exp2 = new NumExpression(Integer.parseInt(elements[++i])); //通過上面的兩個數(shù)字解釋器構(gòu)造加法運(yùn)算解釋器 mExpStack.push(new AdditionExpression(exp1, exp2)); break; default: /* * 如果為數(shù)字,直接構(gòu)造數(shù)字解釋器并壓入棧 */ mExpStack.push(new NumExpression(Integer.valueOf(elements[i]))); break; } } } /** * 計算結(jié)果 * * @return 最終的計算結(jié)果 */ public int calculate(){ return mExpStack.pop().interpreter(); } }
調(diào)用:
public class Client { public static void main(String[] args) { Calculator c = new Calculator("22 + 553 + 83 + 5"); System.out.println("計算結(jié)果:"+c.calculate()); } }
結(jié)果:
計算結(jié)果:663
如果相加如減法的操作,在Calculator中加入相應(yīng)判斷即可:
public class SubtractionExpression extends OperatorExpression{ public SubtractionExpression(ArithemticExpression exp1, ArithemticExpression exp2) { super(exp1, exp2); } @Override public int interpreter() { return exp1.interpreter() - exp2.interpreter(); } }
Calculator中加入:
case '-': exp1 = mExpStack.pop(); exp2 = new NumExpression(Integer.parseInt(elements[++i])); mExpStack.push(new SubtractionExpression(exp1, exp2)); break;
從上面可以看出解釋器模式很靈活,他將復(fù)雜問題可以簡單化、模塊化、分離實(shí)現(xiàn)、解釋執(zhí)行。
六、Android源碼中解釋器模式
1、PackageParser
PackageParser是對AndroidManifest.xml配置文件進(jìn)行讀取的,具體原理參考:解析AndroidManifest原理
七、總結(jié)
優(yōu)點(diǎn):
最大的優(yōu)點(diǎn)使其靈活的擴(kuò)展性,當(dāng)我們想對文法規(guī)則進(jìn)行擴(kuò)展延伸時,只需要增加相應(yīng)的非終結(jié)符解釋器,并在構(gòu)建抽象語法樹時,使用到新增的解釋器對象進(jìn)行具體的解釋即可,非常方便。
缺點(diǎn):
每個語法都要產(chǎn)生一個非終結(jié)符表達(dá)式,語法規(guī)則比較復(fù)雜時,就可能產(chǎn)生大量的類文件,為維護(hù)帶來了非常多的麻煩。
解釋器模式由于使用了大量的循環(huán)和遞歸,效率是個問題,特別是用于解析復(fù)雜、冗長的語法時,效率是難以忍受的。
上述內(nèi)容就是Android中怎么實(shí)現(xiàn)解釋器模式,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。