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

前言

Android的设计模式系列文章介绍,欢迎关注,持续更新中:

1.定义

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

2.介绍

解释器模式属于行为型模式。

解释器模式提供了一种解释语言的语法或表达式的方式。

解释器模式实际开发中很少用到。

3.UML类图

234a156b0210

解释器模式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这个方法中解释。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/550904.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下载人脸认证助手_关于微信人脸解封验证失败方法

微信解封人脸验证失败&#xff01;我知道大家出现了这个问题。嗯&#xff0c;我也是前两天出现过的&#xff0c;前两天我一觉起来打开微信&#xff0c;发现自己的微信被封了。然后我就很着急的去解封。然后他就是让绑银行卡&#xff0c;然后进行实名认证之后进行人脸解封&#…

android照片如何查看时间,Android 获取照片时间

1、手机拍摄的照片(ExifInterface )ExifInterface exifInterface null;try {exifInterface new ExifInterface(oldPath);} catch (Exception e) {e.printStackTrace();}String watermarkTime exifInterface.getAttribute(ExifInterface.TAG_DATETIME);//ExifInterface方法只…

罗宾斯管理学13版pdf_全球著名管理学家,曾任五大高校教授,罗宾斯教你如何做好管理者...

在管理界&#xff0c;除了德鲁克能被称之为管理学大师&#xff0c;还有一位满腹经纶的管理学家&#xff0c;他就是斯蒂芬P罗宾斯&#xff0c;这位全球著名的管理学家&#xff0c;曾先后在布拉斯加大学、协和大学、巴尔的摩大学、南伊利诺伊大学、圣迭戈大学五大高校任教&#x…

img标签默认有外边距吗_你知道css的盒模型吗?

CSS盒子模型与怪异盒模型 盒子模型(Box Modle)可以用来对元素进行布局&#xff0c;包括内边距(padding)&#xff0c;边框(border)&#xff0c;外边距(margin)&#xff0c;和实际内容(content)这几个部分。标准盒模型 标准盒模型中盒子的大小是指&#xff1a;content border p…

js html 转换为富文本,如何将富文本得到的html转换为pdf?

问题描述我想将kindtor最后得到的html转换为pdf&#xff0c;有一种思路是将获得的html通过dom-to-image或者html2canvas转换为图片。在转换为pdf&#xff0c;但是我获得到html之后&#xff0c;运用dom-to-image转换或者html都不行&#xff0c;会报错出来。问题出现的环境背景及…

rust雪山矿洞几个入口_梅里雪山内转全记录(雨崩徒步:神湖神瀑冰湖)

头一次徒步完还愿意记录一下&#xff0c;两个原因吧&#xff1a;1&#xff09;出发前搜雨崩攻略&#xff0c;各大网站都很少有详细且完整的回答&#xff0c;2&#xff09;朋友圈发图后&#xff0c;好多朋友对雨崩有兴趣求攻略。先把此次行程大概列一下&#xff0c;如果还有兴趣…

微型计算机上的南桥芯片功能,微型计算机及接口技术2012年1月真题试题(04732)...

微型计算机及接口技术2012年1月真题试题及答案解析(04732)微型计算机及接口技术2012年1月真题试题及答案解析(04732)&#xff0c;本试卷总分100分。一、单项选择题(本大题共20小题&#xff0c;每小题1分&#xff0c;共20分)在每小题列出的四个备选项中只有一个是符合题目要求的…

空值用前值填充_用Excel进行数据处理

Excel是一款常用的办公软件&#xff0c;它的功能强大&#xff0c;本文我们将学习如何使用Excel 2019进行数据处理。导入数据本文使用的数据来自This Week’s Garbage Data File.xlsx。数据格式如上所示&#xff1a;表示销售日期表示销售人员名称和ID表示销售区域表示总计为了对…

2014年计算机初级应用考试是,2014年国硕士研究生入学统一考试计算机基础试题...

请回答下列问题。(1) 本题中的网络可抽象为数据结构中的哪种逻辑结构?(2) 针对题42表中的内容&#xff0c;设计合理的链式存储结构&#xff0c;以保存题42表中的链路状态信息(LSI)。要求给出链式存储结构的数据类型定义&#xff0c;并画出对应题42表的链式存储结构示意图(示意…

已知三个用不同数制表示的整数_数学一轮复习26,数列的概念及简单表示法,常用方法及具体策略...

【考试要求】1.了解数列的概念和几种简单的表示方法(列表、图象、通项公式)&#xff1b;2.了解数列是自变量为正整数的一类特殊函数.【知识梳理】1.数列的定义按照一定顺序排列着的一列数称为数列&#xff0c;数列中的每一个数叫做这个数列的项.2.数列的分类3.数列的表示法数列…

html播放mp4不显示画面,浏览器播放mp4格式视频时只有声音看不到画面的原因及解决方法(精)...

做HTML5网页&#xff0c;要播放视频&#xff0c;视频格式为mp4&#xff0c;结果浏览器只能听到声音&#xff0c;看不到画面。反复测试&#xff0c;多个浏览器均出现此问题。刚开始以为视频的格式不对&#xff0c;我是从MOV转的MP4格式&#xff0c;反复确认嵌入的视频确实是mp4格…

4j 禁止类输出日志_logback 日志详细讲解

Logback介绍Logback是一个开源日志组件&#xff0c;logback被分为3个组件&#xff0c;logback-core,logback-classic和logback-access.Logback是具体的日志框架&#xff0c;它要与slf4j结合起来使用。Slf4j&#xff1a;简单日志门面&#xff0c;不是具体的日志解决方案&#xf…

计算机桌面桌面设置动态视频,电脑壁纸 篇一:电脑设置动态视频桌面图文教程...

电脑壁纸 篇一&#xff1a;电脑设置动态视频桌面图文教程2019-04-01 11:45:213点赞8收藏0评论今天闲来无事&#xff0c;来张大妈也好久了&#xff0c;没什么技术感觉发文太难了&#xff0c;试着来一篇看看能不能过&#xff01;相信还有大多数值友的电脑桌面都是一张静态的图片壁…

e300氛围灯哪里调节_让快乐来得更简单!体验新宝骏E300/E300 PLUS

有停车焦虑的小伙伴一定都想拥有一辆微型车&#xff0c;无论你多晚回家&#xff0c;只要有一小块空挡就能泊车&#xff0c;然后上楼睡觉。所谓快乐&#xff0c;莫过于此。在纯电动微型车领域&#xff0c;宝骏可以说是经验最为丰富的厂家之一。相继推出了E100和E200&#xff0c;…

太极计算机ehr系统,(数据科学学习手札21)sklearn.datasets常用功能详解

作为Python中经典的机器学习模块&#xff0c;sklearn围绕着机器学习提供了很多可直接调用的机器学习算法以及很多经典的数据集&#xff0c;本文就对sklearn中专门用来得到已有或自定义数据集的datasets模块进行详细介绍&#xff1b;datasets中的数据集分为很多种&#xff0c;本…

权限申请_Android 开发工程师必须掌握的动态权限申请,三步轻松搞定!

Android 6.0 / Android M 发布后&#xff0c;手机权限被分为两种&#xff0c;即&#xff1a;Normal Permission / 正常权限 和Dangerous Permission / 危险权限&#xff0c;更好的保护了用户的隐私&#xff0c;极大提升了系统安全性&#xff01;因此&#xff0c;我们在APP开发过…

什么意思中文翻译_os常见意思介绍

os是一个英文的缩写在不同环境状态下表达的意思不一样的&#xff0c;比如在计算机中就是操作系统的意思&#xff0c;在聊天情景的时候就是内心独白的意思&#xff0c;下面来看看详细的os是什么意思介绍吧。os是什么意思一、计算机中的解释OS其实就是Operating System的缩写中文…

网页证书添加_二、Exchange2016部署及基础配置(NDS及证书配置)

1、DNS轮询负载说明&#xff1a;使用DNS轮询实现负载均衡&#xff0c;最大的优点就是部署简单&#xff0c;基本上不需要成本&#xff0c;如果一台exchange服务器彻底宕机&#xff0c;http客户端(Outlook)足够智能&#xff0c;可以连接到另一台服务器。但DNS轮询并不是真正对流量…

ubuntu中显示本机的gpu_Ubuntu下如何查看GPU版本和使用信息

【转载】nvidia-smi是用来查看GPU版本信息&#xff0c;GPU使用信息查询&#xff1a;nvidia-smi第一栏的Fan&#xff1a;N/A是风扇转速&#xff0c;从0到100%之间变动&#xff0c;这个速度是计算机期望的风扇转速&#xff0c;实际情况下如果风扇堵转&#xff0c;可能打不到显示的…

css html 字竖,CSS实现文字竖排 DIV CSS文字垂直竖列排版显示如何实现?

DIV CSS实现文字竖排排版显示兼容各大浏览器&#xff0c;让文字垂直竖列排版布局。有时我们需要一段文字进行从上到下竖列排版&#xff0c;我们知道CSS样式中有一样式可以让其竖列排版&#xff0c;但所有浏览器不全兼容&#xff0c;逼不得已放弃。但DIVCSS5有2中方法对文字字体…