日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

解释器android,Android的设计模式-解释器模式

發布時間:2025/3/11 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解释器android,Android的设计模式-解释器模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Android的設計模式系列文章介紹,歡迎關注,持續更新中:

1.定義

給定一門語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。

2.介紹

解釋器模式屬于行為型模式。

解釋器模式提供了一種解釋語言的語法或表達式的方式。

解釋器模式實際開發中很少用到。

3.UML類圖

解釋器模式UML類圖.jpg

角色說明:

AbstractExpression(抽象表達式):定義一個抽象的解釋方法,其具體的實現在各個具體的子類解釋器中完成。

TerminalExpression(終結符表達式):實現對文法中與終結符有關的解釋操作。

NonterminalExpression(非終結符表達式):實現對文法中的非終結符有關的解釋操作。

Context(環境角色):包含解釋器之外的全部信息。

Client(客戶端角色):解析表達式,構建抽象語法樹,執行具體的解釋操作等。

4.實現

以加減法的實現為例,我們實現下面表達式的解釋并輸出結果,為了方便解釋,在表達式中介加了空格方便處理。

a = 1024

b = 512

a + b

a - b

4.1 創建抽象表達式

public abstract class ArithmeticExpression {//抽象算術表達式

public abstract Object interpret(Context context);//抽象解釋方法

}

4.2 終結符表達式

從上面的表達式可以看出,終結符有兩種,一種是數字,另外一種是變量。

//數字表達式,用來解釋數字

public class NumExpression extends ArithmeticExpression {

private String strNum;

public NumExpression(String strNum) {

this.strNum = strNum;

}

@Override

public Integer interpret(Context context) {//解釋數字

return Integer.parseInt(strNum);

}

}

//變量表達式,用來解釋變量

class VarExpression extends ArithmeticExpression {

private String var;

public VarExpression(String var) {

this.var = var;

}

@Override

public String interpret(Context context) {//解釋變量

return var;

}

}

4.3 創建非終結符表達式

上面的表達式有三種非終結符,分別是+號、-號和=號。

//加法表達式,用來解釋加法,如a+b

public class AddExpression extends ArithmeticExpression {

private ArithmeticExpression left, right;//加號左右兩邊的內容

public AddExpression(ArithmeticExpression left, ArithmeticExpression right) {

this.left = left;

this.right = right;

}

@Override

public Integer interpret(Context context) {//解釋加法表達式的結果,即算出left+right的結果

return context.get((String) left.interpret(context)) + context.get((String) right.interpret(context));

}

}

//減法表達式,用來解釋減法,如a-b

public class SubExpression extends ArithmeticExpression {

private ArithmeticExpression left, right;//減號左右兩邊的內容

public SubExpression(ArithmeticExpression left, ArithmeticExpression right) {

this.left = left;

this.right = right;

}

@Override

public Integer interpret(Context context) {//解釋減法表達式的結果,即算出left-right的結果

return context.get((String) left.interpret(context)) - context.get((String) right.interpret(context));

}

}

//等號表達式,用來解釋變量賦值,如a=1024

public class EqualExpression extends ArithmeticExpression {

private ArithmeticExpression left, right;//等號左右兩邊的內容

public EqualExpression(ArithmeticExpression left, ArithmeticExpression right) {

this.left = left;

this.right = right;

}

@Override

public Object interpret(Context context) {//解釋等號表達式的結果,并將結果保存到context,變量名為key,值為value

context.put((String) left.interpret(context), (int) right.interpret(context));

return null;

}

}

4.4 創建環境角色

創建環境主要包含解釋器之外的全部信息,這里用來保存變量以及其值。

public class Context {

Map mMap = new HashMap<>();//使用HashMap來保存結果

public void put(String key, int value) {

mMap.put(key, value);

}

public int get(String key) {

return (int) mMap.get(key);

}

}

4.5 創建客戶端角色:

客戶端角色主要負責解析表達式,構建抽象語法樹,執行具體的解釋操作等。

public class Calculator {//計算器類

Context mContext = new Context();

private ArithmeticExpression mExpression;

public void read(String expression) {//讀取表達式

String[] split = expression.split(" ");//表達式以空格隔開,方便拆分

switch (split[1]) {//根據不同符號去執行具體的解析操作

case "=":

new EqualExpression(new VarExpression(split[0]), new NumExpression(split[2])).interpret(mContext);

break;

case "+":

mExpression = new AddExpression(new VarExpression(split[0]), new VarExpression(split[2]));

break;

case "-":

mExpression = new SubExpression(new VarExpression(split[0]), new VarExpression(split[2]));

break;

}

}

public int calculate() {//計算結果

return (int) mExpression.interpret(mContext);

}

}

4.6 客戶端測試:

public void test() {

Calculator calculator = new Calculator();

calculator.read("a = 1024");//讀取表達式

calculator.read("b = 512");

System.out.println("a = 1024");

System.out.println("b = 512");

calculator.read("a + b");

System.out.println("a + b = " + calculator.calculate());//計算結果

calculator.read("a - b");

System.out.println("a - b = " + calculator.calculate());

}

輸出結果:

a = 1024

b = 512

a + b = 1536

a - b = 512

5. 應用場景

簡單的語法需要解釋時,如解釋一個sql語句。

一些重復發生的問題,比如加減乘除四則運算,但是公式每次都不同,有時是a+b-cd,有時是ab+c-d等,公式千變萬化,但是都是由加減乘除四個非終結符來連接的,這時我們就可以使用解釋器模式。

6. 優點

靈活的擴展性,想擴展語法規則時只需新增新的解釋器就可以了。如上面的例子中,想增加乘除法,只想增加相應的解釋類,并增加相應的表達式解釋操作即可。

7. 缺點

每一個文法都至少對應一個解釋器,會產生大量的類,難于維護。

解釋器模式由于大量使用循環和遞歸,需要考慮效率的問題,而且調試也不方便。

對于復雜的文法,構建其抽象語法樹會顯得異常繁瑣。

所以不推薦在重要的模塊中使用解釋器模式,維護困難。

8. Android中的源碼分析

對于AndroidManifest.xml這個文件,我們是相當熟悉。實際上AndroidManifest.xml是由PackageManagerService使用了PackageParser這個類來解釋的,這里面就用到了解釋器模式。對于AndroidManifest.xml中的每一個標簽,都有對應的類去保存相應的信息。

8.1 PackageParser的parseBaseApkCommon方法

基于Android 27的源碼,不同版本的源碼方法名可能不一樣。

private Package parseBaseApkCommon(Package pkg, Set acceptedTags, Resources res,

XmlResourceParser parser, int flags, String[] outError)

throws XmlPullParserException, IOException {

//其他代碼略

if (tagName.equals(TAG_APPLICATION)) {

//其他代碼略

if (!parseBaseApplication(pkg, res, parser, flags, outError)) {//解釋application標簽

return null;

}

} else if (tagName.equals(TAG_OVERLAY)) {

//其他代碼略

} else if (tagName.equals(TAG_KEY_SETS)) {

if (!parseKeySets(pkg, res, parser, outError)) {

return null;

}

} else if (tagName.equals(TAG_PERMISSION_GROUP)) {

if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {

return null;

}

} else if (tagName.equals(TAG_PERMISSION)) {

if (!parsePermission(pkg, res, parser, outError)) {

return null;

}

} else if (tagName.equals(TAG_PERMISSION_TREE)) {

if (!parsePermissionTree(pkg, res, parser, outError)) {

return null;

}

} else if (tagName.equals(TAG_USES_PERMISSION)) {

if (!parseUsesPermission(pkg, res, parser)) {

return null;

}

} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)

|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {

if (!parseUsesPermission(pkg, res, parser)) {

return null;

}

} else if (tagName.equals(TAG_USES_CONFIGURATION)) {

//其他代碼略

} else if (tagName.equals(TAG_USES_FEATURE)) {

//其他代碼略

} else if (tagName.equals(TAG_FEATURE_GROUP)) {

//其他代碼略

} else if (tagName.equals(TAG_USES_SDK)) {

//其他代碼略

} else if (tagName.equals(TAG_SUPPORT_SCREENS)) {

//其他代碼略

} else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {

//其他代碼略

} else if (tagName.equals(TAG_INSTRUMENTATION)) {

//其他代碼略

} else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {

//其他代碼略

} else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {

//其他代碼略

} else if (tagName.equals(TAG_USES_GL_TEXTURE)) {

//其他代碼略

} else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {

//其他代碼略

} else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//

//其他代碼略

} else if (tagName.equals(TAG_EAT_COMMENT)) {

//其他代碼略

} else if (tagName.equals(TAG_PACKAGE)) {

//其他代碼略

} else if (tagName.equals(TAG_RESTRICT_UPDATE)) {

//其他代碼略

} else if (RIGID_PARSER) {

//其他代碼略

} else {

//其他代碼略

}

}

從上面代碼可以看到,就是對各個標簽的內容進行解釋。我們再來看看parseBaseApplication這個方法,這個是對Application進行解釋。

8.2 parseBaseApplication方法

private boolean parseBaseApplication(Package owner, Resources res,

XmlResourceParser parser, int flags, String[] outError)

throws XmlPullParserException, IOException {

//其他代碼略

String tagName = parser.getName();

if (tagName.equals("activity")) {//解釋activity

Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,

owner.baseHardwareAccelerated);

//其他代碼略

} else if (tagName.equals("receiver")) {//解釋receiver

Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,

true, false);

//其他代碼略

} else if (tagName.equals("service")) {//解釋service

Service s = parseService(owner, res, parser, flags, outError, cachedArgs);

//其他代碼略

} else if (tagName.equals("provider")) {//解釋provider

Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);

//其他代碼略

} else if (tagName.equals("activity-alias")) {

Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);

//其他代碼略

} else if (parser.getName().equals("meta-data")) {

//其他代碼略

} else if (tagName.equals("static-library")) {

//其他代碼略

} else if (tagName.equals("library")) {

//其他代碼略

} else if (tagName.equals("uses-static-library")) {

if (!parseUsesStaticLibrary(owner, res, parser, outError)) {

return false;

}

} else if (tagName.equals("uses-library")) {

//其他代碼略

} else if (tagName.equals("uses-package")) {

//其他代碼略

} else {

//其他代碼略

}

//其他代碼略

return true;

}

可以看到,上面有對activity、receiver、service等標簽的解釋,activity的具體解釋在parseActivity這個方法里面,有興趣的可以自行去看下,這里就不細說了,同時可以看到receiver也是在parseActivity這個方法中解釋。

總結

以上是生活随笔為你收集整理的解释器android,Android的设计模式-解释器模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。