第十章、解释器模式

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

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

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. [转]Linux的SOCKET编程详解

    From : http://blog.csdn.net/hguisu/article/details/7445768 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在 ...

  2. 日历控件My97DatePicker WdatePicker屏蔽 onchange的解决方法

    http://www.cnblogs.com/wan-feng/archive/2013/12/13/3473439.html 受下面文章的启发,使用DatePicker自带的年月日相关的change ...

  3. UrlRewriter && IIS7

    为了在动态网站获得更好的url体验,往往采用url重写技术. 比如:http://blog.xujif.com/?p=268 可以重写为 http://blog.xujif.com/archives/ ...

  4. 第一章 Java加解密简介

    1.加密算法: 移位.替代(古典加密) 对称加密:DES.AES 非对称加密:RSA 散列函数算法(单向加密):MD5.SHA.Mac 数字签名算法:RSA.DSA 其中,前三种主要完成数据的加解密: ...

  5. JQuery之ContextMenu(右键菜单)

    插件下载地址:http://www.trendskitchens.co.nz/jquery/contextmenu/jquery.contextmenu.r2.js压缩版:http://www.tre ...

  6. Laravel SQL 查询语句集锦

    1.从数据表中取得单一数据列 $user= DB::table('users')->where('name','John')->first(); 2.检索表中的所有行 复制代码代码如下: ...

  7. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十一)定制一个arvo格式文件发送到kafka的topic,通过Structured Streaming读取kafka的数据

    将arvo格式数据发送到kafka的topic 第一步:定制avro schema: { "type": "record", "name": ...

  8. Linux中挂载新的磁盘到指定目录或分区

    新增磁盘的设备文件名为 /dev/vdb 大小为100GB. #fdisk -l  查看新增的的磁盘 1.对新增磁盘进行分区 #fdisk /dev/vdb 按提示操作 p打印  n新增 d 删除 w ...

  9. 杂谈:大容量(T级容量)的网盘的意义

    这两天,大容量的网盘的消息不断的推出.有百度的网盘推1T容量的:有腾讯的推10T容量的:有的还推不限容量的等等不一而足. 先看看大容量网盘的历史 早先是没有网盘这个概念的.能提供免费空间是电子邮箱 早 ...

  10. PHPCMS源码分析

    PHPCMS 一.模版引擎 如:调用单页面index.php?m=content&c=index&a=lists&catid=9.1.先获取到模版变量的值$template_l ...