《Android源代碼設計模式解析與實戰》讀書筆記(十)
第十章、解釋器模式
解釋器模式是一種用的比較少的行為型模式。其提供了一種解釋語言的語法或表達式的方式。
可是它的使用場景確實非常廣泛,僅僅是由於我們自己非常少回去構造一個語言的文法,所以使用較少。
1.定義
給定一個語言,定義它的文法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。
(當中語言就是我們須要解釋的對象,文法就是這個語言的規律,解釋器就是翻譯機。通過文法來翻譯語言。)
2.使用場景
1.假設某個簡單的語言須要解釋運行並且能夠將該語言中的語句表示為一個抽象的語法樹時能夠考慮使用解釋器模式。
2.在某些特定的領域出現不斷反復的問題時,能夠將該領域的問題轉化為一種語法規則下的語句。然後構建解釋器來解釋該語句。
3.簡單實現
我們使用解釋器模式對“m+n+p”這個表達式進行解釋,那麽代表數字的m、n和p就能夠看成終結符號,而“+”這個運算符號能夠當做非終結符號。
TerminalExpression:終結符表達式,實現文法中與終結符有關的解釋操作。文法中每一個終結符都有一個詳細的終結表達式與之相應。
NonterminalExpression :非終結符表達式,實現文法中與非終結符有關的解釋操作。非終結符表達式依據邏輯的復雜程度而添加。原則上每一個文法規則都相應一個非終結符表達式。
抽象的算數運算解釋器
public abstract class ArithemticExpression {
/**
* 抽象的解析方法
* 詳細的解析邏輯由詳細的子類實現
*
* @return 解析得到詳細的值
*/
public abstract int interpreter();
}
數字解釋器
public class NumExpression extends ArithemticExpression{
private int num;
public NumExpression(int num){
this.num = num;
}
@Override
public int interpreter() {
return num;
}
}
運算符號解釋器
public abstract class OperatorExpression extends ArithemticExpression{
protected ArithemticExpression exp1, exp2;
public OperatorExpression(ArithemticExpression exp1, ArithemticExpression exp2){
this.exp1 = exp1;
this.exp2 = exp2;
}
}
詳細的加法運算符解釋器
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棧儲存並操作全部相關的解釋器
private Stack<ArithemticExpression> mExpStack = new Stack<ArithemticExpression>();
public Calculator(String expression){
//聲明兩個ArithemticExpression類型的暫時變量,儲存運算符左右兩邊的數字解釋器
ArithemticExpression exp1,exp2;
//依據空格切割表達式字符串(比方1 + 2 + 3 + 4)
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.parseInt(elements[++i]));
//通過上面的兩個數字解釋器構造加法運算解釋器
mExpStack.push(new AdditionExpression(exp1, exp2));
break;
default:
/*
* 假設為數字,直接構造數字解釋器並壓入棧
*/
mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
break;
}
}
}
/**
* 計算結果
*
* @return 終於的計算結果
*/
public int calculate(){
return mExpStack.pop().interpreter();
}
}
調用
public class Client {
public static void main(String[] args) {
Calculator c = new Calculator("22 + 553 + 83 + 5");
System.out.println("計算結果:"+c.calculate());
}
}
結果:
計算結果:663
假設相加如減法的操作,在Calculator中添加相應推斷就可以:
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;
從上面能夠看出解釋器模式非常靈活,他將復雜問題能夠簡單化、模塊化、分離實現、解釋運行。
4.Android源代碼中的模式實現
1.PackageParser
PackageParser是對AndroidManifest.xml配置文件進行讀取的,詳細原理參考:解析AndroidManifest原理
5.總結
1.長處
最大的長處使其靈活的擴展性,當我們想對文法規則進行擴展延伸時。僅僅須要添加相應的非終結符解釋器,並在構建抽象語法樹時。使用到新增的解釋器對象進行詳細的解釋就可以,非常方便。
2.缺點
1.每一個語法都要產生一個非終結符表達式,語法規則比較復雜時。就可能產生大量的類文件,為維護帶來了非常多的麻煩。
2.解釋器模式由於使用了大量的循環和遞歸。效率是個問題,特別是用於解析復雜、冗長的語法時,效率是難以忍受的。
6.參考
參考鏈接:解釋器模式 詳細解釋
《Android源代碼設計模式解析與實戰》讀書筆記(十)