《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源代码设计模式解析与实战》读书笔记(十)的更多相关文章
- CSS揭秘读书笔记 (一)
CSS揭秘读书笔记 (一) 一.半透明边框 要想实现半透明边框可以使用border: border: 10px solid hsla(0,0%,100%,.5); background: ...
- 《CSS世界》笔记二:盒模型四大家族
上一篇:<CSS世界>笔记一:流/元素/尺寸下一篇:<CSS世界>笔记三:内联元素与对齐 写在前面 在读<CSS世界>第四章之前,粗浅的认为盒模型无非是margin ...
- 《精通CSS》读书笔记(一)
最近新添16本书,目前开始看陈剑瓯翻译的<精通CSS——高级Web标准解决方案>(Andy Budd, CSS Mastery -- Advanced Web Standards Solu ...
- 《css世界》笔记之流、元素与基本尺寸
1. 块级元素 基本特性:就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示. 块级元素和"display 为block 的元素"不是一个概念,display:list- ...
- css 揭秘-读书笔记
css 揭秘 [希]Lea verou 著 css 魔法 译 该书涵盖7大主题,47个css技巧,是css进阶必备书籍,开阔思路,探寻更优雅的解决方案.这本书完全用css渲染出的html写成的(布局. ...
- JavaScript权威设计--CSS(简要学习笔记十六)
1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...
- JavaScript权威设计--JavaScript脚本化文档Document与CSS(简要学习笔记十五)
1.Document与Element和TEXT是Node的子类. Document:树形的根部节点 Element:HTML元素的节点 TEXT:文本节点 >>HtmlElement与 ...
- 《Two Days DIV + CSS》读书笔记——CSS选择器
1.1.2 CSS选择器 CSS 选择器最基本的有四种:标签选择器.ID 选择器.类选择器.通用选择器. [标签选择器] 一个完整的 HTML 页面由很多不同的标签组成,而标签选择器,则是决定哪些标签 ...
- 《Two Days DIV + CSS》读书笔记——CSS控制页面方式
1.1 你必须知道的知识 (其中包括1.1.1 DIV + CSS的叫法解释:1.1.2 DIV + CSS 名字的误区:以及1.1.3 W3C简介.由于只是背景知识,跳过该章.) 1.2 你必须掌握 ...
- CSS Grid 读书笔记
基本概念 MDN上的解释是这样的 CSS Grid Layout excels at dividing a page into major regions or defining the relati ...
随机推荐
- CoreDNS介绍
本文介绍 CoreDNS 相关配置以及验证方法,实验环境为 Kubernetes 1.11,搭建方法参考kubeadm安装kubernetes V1.11.1 集群 busybox 的槽点 开始之前先 ...
- hive php连接查询
baidu hive php PHP连接Hive执行sql查询 php通过 thrift访问hadoop的hive php开发Hive Web查询 php连接hive执行sql查询 利用python将 ...
- 使用python type动态创建类
使用python type动态创建类 X = type('X', (object,), dict(a=1)) # 产生一个新的类型 X 和下列方法class X(object): a = 1效 ...
- window.parent window.top window.parent.location.pathname 没权限
跨域问题啊,如果只是测试的话,放到服务器去测试,本地的(http://localhost/)就算是在同一个文件下,都会被认为跨域的.如果不需要支持低版本IE浏览,可以使用postMessage处理这个 ...
- 不知道哪里alert undefined 用下面的语句是js报错.F12能提示报错的地方window.alert=function(aa){ if (typeof (aa)"undefined"){ throw "就是这";}};
不知道哪里alert undefined 用下面的语句是js报错.F12能提示报错的地方 var oldalert=window.alert; window.alert=function(aa){ i ...
- 一致性哈希算法(consistent hashing)(转)
原文链接:每天进步一点点——五分钟理解一致性哈希算法(consistent hashing) 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网 ...
- .Net-using-Class:MemoryCache 类
ylbtech-.Net-using-Class:MemoryCache 类 初始化 System.Runtime.Caching.MemoryCache 类的新实例. 1. 程序集 System.R ...
- verilog语法实例学习(6)
函数和任务 函数 https://wenku.baidu.com/view/d31d1ba8dd3383c4bb4cd283.html verilog中函数的目的是允许代码写成模块的方式而不是定义独立 ...
- 读书笔记,《Java 8实战》,第四章,引入流
集合是Java中使用最多的API,但集合操作却远远算不上完美.主要表现在两点, 第一,集合不能让我们像数据库的SQL语言一样用申明式的语言指定操作: 第二,现在的集合API无法让我们 ...
- Set Matrix Zeroes leetcode java
题目: Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. cl ...