Android中的設計模式之解釋器模式

參考

  • 《設計模式:可複用面向對象軟件的基礎 》5.3 Interpreter 解釋器 類行爲型模式
  • 《Android源碼設計模式解析與實戰》第10章 化繁爲簡的翻譯機--解釋器模式

意圖

給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器適用該表示來解釋語言中的句子。java

適用場景

當有一個語言須要解釋執行,而且你可將該語言中的句子表示爲一個抽象語法樹時,可以使用解釋器模式。而當存在如下狀況時該模式效果最好:express

  • 該文法簡單對於複雜的文法,文法的類層次變得龐大而又沒法管理。
  • 效率不是一個關鍵問題最高效的解釋器一般不是經過直接解釋語法分析樹實現的,而是首先將它們轉換爲另外一種形式。

非終結符號與終止符號

例:設計模式

S ::= abA*ef
A ::= cd

符號「::=」表示推導;符號「*」表示閉包,意思就是符號A能夠有0或有N個重複;S和A稱爲非終結符號,由於他們能推導出式子右邊的表達式,同時又由於整個推導式是從S出發的,所以,這個S也稱爲初始符號;而abef和cd這些字符不能再被推導咱們稱之爲終結符號。數組

結構

interpreterPattern

  • AbstractExpression 抽象表達式,聲明一個抽象的解釋操做父類,並定義了一個抽象的解釋方法,其具體的實如今各個具體的子類解釋器中完成。
  • TeminalExpression 終結符表達式,實現文法中與終結符有關的解釋操做。
  • NonterminalExpression 非終結符表達式,實現文法中與非終結符有關的解釋操做。
  • Context 上下文環境類,包含解釋器以外的全局信息。
  • Client 客戶端類,解析表達式,構建抽象語法樹,執行具體的解釋表達操做等。

優勢

靈活的擴展性,當咱們想對文法規則進行擴展延伸時,只須要增長相應的非終結符解釋器,並在構建抽象語法樹時,使用到新增的解釋器對象進行具體的解釋便可,比較方便。閉包

缺點

每一條文法都對應一個解釋器,會生成大量類,致使後期維護困難。同時,對於過於複雜的文法,構建其抽象語法樹會顯得異常繁瑣,所以,對於複雜的文法並不推薦使用解釋器模式。ide

例子1

描述

表達式「m+n+p」,若是咱們使用解釋器模式對該表達式進行解釋,那麼表明數字的m,n,和p三個字母咱們就能夠當作是終結符號,而「+」這個算術運算符號則可看成非終結符,同時咱們能夠先建立一個抽象解釋器表示數學運算。this

結構

結構

代碼實現

/**
 *  算術運算解釋器抽象類
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:22
 */
public  abstract  class AthmeticExpression {
    /**
     * 抽象的解析方法
     * @return 解析獲得的值
     */
    abstract int interpreter();
}

/**
 *  數字解釋器,只爲了解釋數字
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:24
 */
public class NumExpression extends AthmeticExpression {
    private int num;
    public NumExpression(int num){
        this.num = num;
    }
    @Override
    int interpreter() {
        return num;
    }
}


/**
 *  運算符解釋器
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:27
 */
public abstract class OperatorExpression extends AthmeticExpression {
    /**
     * 運算符兩邊的表達式
     */
    protected AthmeticExpression exp1,exp2;

    public OperatorExpression(AthmeticExpression exp1, AthmeticExpression exp2) {
        this.exp1 = exp1;
        this.exp2 = exp2;
    }

}

/**
 *  加法解釋器
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:29
 */
public class AdditionExpressoin extends OperatorExpression {
    public AdditionExpressoin(AthmeticExpression exp1, AthmeticExpression exp2) {
        super(exp1, exp2);
    }

    /**
     * 具體解釋+符號
     * @return 解釋結果
     */
    @Override
    int interpreter() {
        return exp1.interpreter()+exp2.interpreter();
    }
}


/**
 *  計算器類
 * @author newtrekWang
 * @email  wangjiaxing20160101@gmail.com
 * @time   2018/8/19  23:30
 */
public class Calculator {
    /**
     * 用一個棧存儲並操做全部相關的解釋器
     */
    private Stack<AthmeticExpression> mExpStack = new Stack<>();

    public Calculator(String  expression){
        AthmeticExpression exp1,exp2;
        // 以空格分開元素
        String[] elements = expression.split(" ");
        for (int i = 0;i<elements.length;i++){
            switch (elements[i].charAt(0)){
                // 若是爲‘+’
                case '+':
                    // 將棧中的解釋器彈出做爲運算符左邊的解釋器
                    exp1 = mExpStack.pop();
                    // 同時將運算符數組下標下一個元素構造爲一個數字解釋器
                    exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                    mExpStack.push(new AdditionExpressoin(exp1,exp2));
                    break;
                    default:
                        // 若是爲數字
                        mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                        break;
            }
        }
    }

    /**
     * 最終結算結果
     * @return
     */
    public int calculate(){
        return mExpStack.pop().interpreter();
    }
}

public static void main(String[] args){
        Calculator calculator = new Calculator("3 + 8 + 2");
        System.out.println(calculator.calculate());
    }

輸出結果:spa

13

應用例子2 Android源碼中的PackageParser

相關文章
相關標籤/搜索