第十章、解释器模式

解释器模式是一种用的比較少的行为型模式。其提供了一种解释语言的语法或表达式的方式。

可是它的使用场景确实非常广泛,仅仅是由于我们自己非常少回去构造一个语言的文法,所以使用较少。

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源代码设计模式解析与实战》读书笔记(十)的更多相关文章

  1. CSS揭秘读书笔记 (一)

    CSS揭秘读书笔记      (一) 一.半透明边框 要想实现半透明边框可以使用border: border: 10px  solid  hsla(0,0%,100%,.5); background: ...

  2. 《CSS世界》笔记二:盒模型四大家族

    上一篇:<CSS世界>笔记一:流/元素/尺寸下一篇:<CSS世界>笔记三:内联元素与对齐 写在前面 在读<CSS世界>第四章之前,粗浅的认为盒模型无非是margin ...

  3. 《精通CSS》读书笔记(一)

    最近新添16本书,目前开始看陈剑瓯翻译的<精通CSS——高级Web标准解决方案>(Andy Budd, CSS Mastery -- Advanced Web Standards Solu ...

  4. 《css世界》笔记之流、元素与基本尺寸

    1. 块级元素 基本特性:就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示. 块级元素和"display 为block 的元素"不是一个概念,display:list- ...

  5. css 揭秘-读书笔记

    css 揭秘 [希]Lea verou 著 css 魔法 译 该书涵盖7大主题,47个css技巧,是css进阶必备书籍,开阔思路,探寻更优雅的解决方案.这本书完全用css渲染出的html写成的(布局. ...

  6. JavaScript权威设计--CSS(简要学习笔记十六)

    1.Document的一些特殊属性 document.lastModified document.URL document.title document.referrer document.domai ...

  7. JavaScript权威设计--JavaScript脚本化文档Document与CSS(简要学习笔记十五)

    1.Document与Element和TEXT是Node的子类. Document:树形的根部节点 Element:HTML元素的节点 TEXT:文本节点   >>HtmlElement与 ...

  8. 《Two Days DIV + CSS》读书笔记——CSS选择器

    1.1.2 CSS选择器 CSS 选择器最基本的有四种:标签选择器.ID 选择器.类选择器.通用选择器. [标签选择器] 一个完整的 HTML 页面由很多不同的标签组成,而标签选择器,则是决定哪些标签 ...

  9. 《Two Days DIV + CSS》读书笔记——CSS控制页面方式

    1.1 你必须知道的知识 (其中包括1.1.1 DIV + CSS的叫法解释:1.1.2 DIV + CSS 名字的误区:以及1.1.3 W3C简介.由于只是背景知识,跳过该章.) 1.2 你必须掌握 ...

  10. CSS Grid 读书笔记

    基本概念 MDN上的解释是这样的 CSS Grid Layout excels at dividing a page into major regions or defining the relati ...

随机推荐

  1. gradle新建工程,多项目依赖,聚合工程

    感谢gradle完全的文档.开始完全没想过新建项目会弄我一天时间,都说gradle构建项目简单,我现在回复他们呵呵. gradle是个非常复杂的工具,从他的完整包80M和72章官方文档就可以看出一二. ...

  2. MYSQL中group_concat有长度限制!默认1024(转载)

    在mysql中,有个函数叫“group_concat”,平常使用可能发现不了问题,在处理大数据的时候,会发现内容被截取了,其实MYSQL内部对这个是有设置的,默认不设置的长度是1024,如果我们需要更 ...

  3. 基于Vue、Bootstrap的Tab形式的进度展示

    最近基于Vue.Bootstrap做了一个箭头样式的进度展示的单页应用,并且支持了对于一个本地JS文件的检索,通过这个单页应用,对于Vue的理解又深入了一些.在这里把主要的代码分享出来. 本单页应用实 ...

  4. Orchard之模版开发

    生成新模版之后(参看:Orchard之生成新模板),紧接着就是模版开发了. 一:开发必备之 Shape Tracing 到了这一步,非常依赖一个工具,当然,它也是 Orchard 项目本身的一个 Mo ...

  5. 【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang

    点分治 Orz hzwer 倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误…… 1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移. ...

  6. dubbo源码解析-spi(一)

    前言 虽然标题是dubbo源码解析,但是本篇并不会出现dubbo的源码,本篇和之前的dubbo源码解析-简单原理.与spring融合一样,为dubbo源码解析专题的知识预热篇. 插播面试题 你是否了解 ...

  7. ProDinner

    ylbtech-dbs:ProDinner A, 数据库关系图 返回顶部 4, 点餐关系图 3, 留言图 1, 用户角色关系图 0, B,SQL脚本返回顶部 2, use master go --ki ...

  8. Asp.Net MVC3 简单教程(三)详解Controller之Filter 【转】

    前言 前面两篇写的比较简单,刚开始写这个系列的时候我面向的对象是刚开始接触Asp.Net MVC的朋友,所以写的尽量简单.所以写的没多少技术含量.把这些技术总结出来,然后一简单的方式让更多的人很好的接 ...

  9. Centos 7安装protobuf3.6.1

    新版本 google protobuf-3.6.1是现在最新版本,添加了新的特性,看说明 下载地址 https://github.com/protocolbuffers/protobuf/releas ...

  10. The node (XXX.XXX.XXX.XXX,XXX.XXX.XXX.XXX)has already some ScaleIO components installed

    安装ScaleIO 1.32遇到如下报错, 怎么办?   很简单, 在控制面板里把ScaleIO的软件删掉即可.