第十章、解释器模式

解释器模式是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式。但是它的使用场景确实很广泛,只是因为我们自己很少回去构造一个语言的文法,所以使用较少。

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;}@Overridepublic 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);}@Overridepublic 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);}@Overridepublic 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. OREILLY Programming .NET 3.5 读书笔记之一

    OREILLY Programming .NET 3.5 读书笔记之一 <Programming .NET 3.5>是OREILLY 2008.08出版的.NET 3.5 开发书籍,作者是 ...

  2. 主成分分析碎石图_ISLR读书笔记十九:主成分分析(PCA)

    本文使用 Zhihu On VSCode 创作并发布 前面写的一些统计学习方法都是属于监督学习(supervised learning),这篇主成分分析(principal components an ...

  3. 计算机英语读书笔记,大学英文读书笔记范文英语读书笔记十篇带翻译.doc

    大学英文读书笔记范文英语读书笔记十篇带翻译 My Room This is my room. Near the window there is a desk. I often do my homewo ...

  4. 图解HTTP读书笔记(十)

    图解HTTP读书笔记(十) Web的攻击技术 HTTP协议本身并不存在安全性问题,因此协议本身几乎不会成为攻击对象.应用HTTP协议的服务器和客户端,以及运行在服务器上的Web应用资源才是攻击目标. ...

  5. 《Programming in Scala》读书笔记(持续更新) - passover的个人空间 - DOIT博客 - 多易网...

    <Programming in Scala>读书笔记(持续更新) - passover的个人空间 - DOIT博客 - 多易网 <Programming in Scala>读书 ...

  6. PHP第十次实验总结,The Clean Architecture in PHP 读书笔记(十)

    laravel 这是clean architecture的第十篇,也是具体案例的第二篇,本篇会通过使用laravel框架,来开发我们的应用. 本文为系列文章的第十篇,完成的目录请查看Clean Arc ...

  7. 《联邦学习实战》杨强 读书笔记十四——构建公平的大数据交易市场

    当数据具有资产属性之后,数据便可以直接或者间接地为公司.为社会创造价值和收益,并且可以作为一种特殊的商品在市场中进行交易. 与传统的商品交易相比,数据资产交易的市场前景更广阔,但同时也面临着很多的挑战 ...

  8. 《Programming in Lua 3》读书笔记(十二)

    日期:2014.7.14 PartⅡ Object-Oriented Programming Lua中实现面向对象编程. "如同OOP对象,table拥有状态:如同OOP对象,table拥有 ...

  9. 《Programming in Lua 3》读书笔记(十)

    这一部分应该挺重要的,Lua中唯一的数据结构便是table,几乎所有的的数据操作都是在table的基础上进行.而本文提到的元表和元方法,便是帮助table实现更强大的功能而设计的. 日期:2014.7 ...

  10. 《把时间当作朋友》读书笔记(十四)--积累(二)

    节省与否 有些钱真不能省,否则注定"屌丝"一生,因为这种"节省"可能会伴随有很高的隐性成本,或者将来造成很大的负担----今天看来省了,可将来却要因此付出极大的 ...

最新文章

  1. 开源大数据周刊-2018年08月10日 第96期
  2. suList() 和 asList()
  3. 小白自学前端,轻松月入过万哦!
  4. inputstream的大小为0_刘科排列三第2020306期推荐:独胆参考0,双胆0和7
  5. CVPR 2020 论文大盘点-目标检测篇
  6. python数据结构剑指offer-从尾到头打印链表
  7. 安装和使用memcached
  8. openstack changePassword
  9. pdf转cad格式工具控件pdf2cad
  10. word复制公式程序无响应
  11. 基于SIMULINK的AWGN信道仿真
  12. jQuery手机版日历插件带农历
  13. String的spilt()方法
  14. FFmpeg 异常:height not divisible by 2
  15. 笔记本电脑换新硬盘重装系统经验
  16. extern 用法简单示例
  17. verilog对信号二分频 时钟分频信号作为时钟使能信号
  18. 非常详尽,多图慎入:Wayland与Weston简介
  19. 电视机接口中英文介绍
  20. Java期中考试总结(甘琳凤)

热门文章

  1. 唯一摩尔斯密码词 leetcode Java篇
  2. C语言 统计英语文章单词的数目
  3. 职场中如何谈加薪,这么谈,成了也等于失败
  4. 信息系统开发与管理【三】之 系统开发方法概述
  5. 软件测试工程师面试的时候可能被提到的问题
  6. 你公司的虚拟机还闲着?基于 Jenkins 和 Kubernetes 的持续集成测试实践了解一下!...
  7. 一个barcode 多个 sku号_互联网洪流之下:美的已悄悄变成一个科技集团|36氪专访...
  8. shell字符串切割 去除文件名后缀
  9. 折纸多少次可以达到珠穆朗玛峰的高度
  10. python:鸡尾酒疗法