口译员设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.简介 2.什么是口译员设计模式 3.实施口译员设计模式 4.何时使用口译员设计模式 5. JDK中的解释器设计模式 6.下载源代码

1.简介

口译员设计模式是一种重型模式。 这一切都是关于通过创建针对自己的编程语言的解释器来组合自己的编程语言,或处理现有的编程语言。 要使用这种模式,您必须对正规语法有一定的了解,才能将一种语言组合在一起。 可以想象,这是开发人员每天都不会真正使用的模式之一,因为创建自己的语言并不是很多人要做的事情。

例如,就形式语法而言,以新语言定义表达式可能类似于以下代码片段:

expression ::= <command> | <repetition> | <sequence>

那么,使用新语言的每个表达式可能由命令,命令的重复和序列表达式组成。 每个项目都可以使用解释方法表示为一个对象,以将您的新语言翻译成可以在Java中运行的语言。

为了说明解释器设计模式的用法,我们创建一个示例来解决简单的数学表达式,但在此之前,让我们在下面的部分中讨论有关解释器设计模式的一些详细信息。

2.什么是口译员设计模式

给定一种语言,请定义其语法的表示形式,以及使用该表示形式来解释该语言句子的解释器。

通常,语言由一组语法规则组成。 遵循这些语法规则可以构建不同的句子。 有时应用程序可能需要处理重复出现的相似请求,这些请求是一组语法规则的组合。 这些请求是不同的,但从某种意义上来说它们是相似的,因为它们都是使用同一组规则构成的。

一个简单的例子就是提交给计算器程序的一组不同的算术表达式。 尽管每个这样的表达式都不同,但是它们都是使用构成算术表达式语言语法的基本规则构造的。

在这种情况下,代替将每个不同的规则组合视为一个单独的案例,对应用程序来说,具有解释规则的通用组合的能力可能是有益的。 解释器模式可用于在应用程序中设计此功能,以便其他应用程序和用户可以使用由一组语法规则定义的简单语言来指定操作。

可以将类层次结构设计为表示语法规则集,而层次结构中的每个类都表示一个单独的语法规则。 可以将解释器模块设计为解释使用上面设计的类层次结构构造的句子,并执行必要的操作。

由于每个语法规则都代表一个不同的类别,因此类别的数量会随着语法规则的数量而增加。 具有广泛而复杂的语法规则的语言需要大量的类。 语法简单时,解释器模式最有效。 具有简单的语法避免了需要具有许多与所涉及的复杂规则集相对应的类,而这些类很难管理和维护。

图1-类图

图1-类图

抽象表达

  • 声明抽象语法树中所有节点共有的抽象Interpret操作。

终端表达

  • 实现与语法中的终端符号关联的Interpret操作。
  • 句子中每个终端符号都需要一个实例。

非末端表达

  • 语法中的每个规则R ::= R1 R2 ... Rn都需要一个这样的类。
  • 为每个符号R1Rn维护类型AbstractExpression实例变量。
  • 为语法中的非终结符实现Interpret操作。 Interpret通常对表示R1Rn的变量进行递归调用。

语境

  • 包含解释器的全局信息。

客户

  • 构建(或给定)抽象语法树,该语法树以语法定义的语言表示特定的句子。 抽象语法树是根据NonterminalExpressionTerminalExpression类的实例组装而成的。
  • 调用Interpret操作。

3.实施口译员设计模式

package com.javacodegeeks.patterns.interpreterpattern;public interface Expression {public int interpret();
}

所有不同的具体表达式都使用上面的接口,并且覆盖了解释方法以定义它们在表达式上的特定操作。

以下是特定于操作的表达式类。

package com.javacodegeeks.patterns.interpreterpattern;public class Add implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Add(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() + rightExpression.interpret();}}
package com.javacodegeeks.patterns.interpreterpattern;public class Product implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Product(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() * rightExpression.interpret();}
}
package com.javacodegeeks.patterns.interpreterpattern;public class Substract implements Expression{private final Expression leftExpression;private final Expression rightExpression;public Substract(Expression leftExpression,Expression rightExpression ){this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic int interpret() {return leftExpression.interpret() - rightExpression.interpret();}}
package com.javacodegeeks.patterns.interpreterpattern;public class Number implements Expression{private final int n;public Number(int n){this.n = n;}@Overridepublic int interpret() {return n;}}

下面是可选的实用程序类,其中包含用于执行表达式的不同实用程序方法。

package com.javacodegeeks.patterns.interpreterpattern;public class ExpressionUtils {public static boolean isOperator(String s) {if (s.equals("+") || s.equals("-") || s.equals("*"))return true;elsereturn false;}public static Expression getOperator(String s, Expression left,	Expression right) {switch (s) {case "+":return new Add(left, right);case "-":return new Substract(left, right);case "*":return new Product(left, right);}return null;}}

现在,让我们测试示例。

package com.javacodegeeks.patterns.interpreterpattern;import java.util.Stack;public class TestInterpreterPattern {public static void main(String[] args) {String tokenString = "7 3 - 2 1 + *";Stack<Expression> stack = new Stack<>();String[] tokenArray = tokenString.split(" ");for (String s : tokenArray) {if (ExpressionUtils.isOperator(s)) {Expression rightExpression = stack.pop();Expression leftExpression = stack.pop();Expression operator = ExpressionUtils.getOperator(s, leftExpression,rightExpression);int result = operator.interpret();stack.push(new Number(result));} else {Expression i = new Number(Integer.parseInt(s));stack.push(i);}}System.out.println("( "+tokenString+" ): "+stack.pop().interpret());}}

上面的代码将提供以下输出:

( 7 3 - 2 1 + * ): 12

请注意,我们已使用后缀表达式来解决它。

如果您不了解后缀,则这里有一个简短的介绍。 数学表达式有三种表示法,即中缀,后缀和前缀。

  • 前缀表示法是常用的算术和逻辑公式表示法,其中运算符在它们所作用的操作数之间(例如3+4以infix样式编写。
  • 后缀也称为反向波兰表示法(RPN)是一种数学表示法,其中每个运算符都遵循其所有操作数,例如34+
  • 前缀 (波兰表示法)是一种用于逻辑,算术和代数的表示法,其中运算符位于其操作数的左侧,例如+34

Infix表示法通常在数学表达式中使用。 编程语言的解释程序将其他两个符号用作数学表达式的语法。

在上面的类中,我们在tokenString变量中声明了表达式的后缀。 然后,我们拆分tokenString并将其分配到一个数组tokenArray 。 在逐个迭代令牌时,首先我们检查了令牌是运算符还是操作数。 如果令牌是操作数,则将其推入堆栈,但如果是运算符,则从堆栈中弹出前两个操作数。 ExpressionUtilsgetOperation方法根据传递给它的运算符返回适当的表达式类。

然后,我们解释结果并将其推回堆栈。 迭代完整的tokenList我们得到了最终结果。

4.何时使用口译员设计模式

有一种要解释的语言时,请使用解释器模式,并且可以将语言中的语句表示为抽象语法树。 解释器模式在以下情况下效果最佳

  • 语法很简单。 对于复杂的语法,语法的类层次结构会变得庞大且难以管理。 在这种情况下,解析器生成器之类的工具是更好的选择。 他们可以在不构建抽象语法树的情况下解释表达式,这可以节省空间并可能节省时间。
  • 效率不是关键问题。 通常,最有效的解释器不是通过直接解释解析树来实现的,而是先将其转换为另一种形式。 例如,正则表达式通常被转换为状态机。 但是即使那样,翻译器也可以通过Interpreter模式实现,因此该模式仍然适用。

5. JDK中的解释器设计模式

  • java.util.Pattern
  • java.text.Normalizer
  • java.text.Format

6.下载源代码

这是关于口译员设计模式的课程。 您可以在此处下载源代码: InterpreterPattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/interpreter-design-pattern.html

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

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

相关文章

「Unity」UGUI的Text实现首行缩进的办法

我的Unity版本&#xff1a;5.3.5f1 直接说正事 Unity的Text组件&#xff0c;想实现代码拿到一段话&#xff0c;在前面加个缩进&#xff0c;让之后的字符依次后移。 有人觉得很简单&#xff0c;然后就这样写了&#xff1a; 但是尝试过的人就会发现&#xff0c;如果用代码在最前…

在Eclipse中配置Tomcat7.0

为了在Eclipse中进行struts2的测试,才发现自己机器上的Eclipse没有集成Tomcat,在网上找了半天&#xff0c;不是这个插件没有下载地址&#xff0c;就是那个有好多注意事项或者版本问题。结果&#xff0c;自己到tomcatforEclipse的插件的网上直接下载了一个&#xff0c;按照提供的…

Datepicker

本文翻译自官网&#xff1a; https://angular-ui.github.io/bootstrap 目录&#xff1a; 1. DatePicker 2. DatePicker popup 一、DatePicker https://angular-ui.github.io/bootstrap/#/datepicker 1. 三种模式 Datepicker是灵活&#xff0c;完全可定制的。它有3种模式&#…

cobertura 使用_使用Cobertura,JUnit,HSQLDB,JPA涵盖您的测试

cobertura 使用你好&#xff01;你好吗&#xff1f; 今天让我们谈谈一个非常有用的工具&#xff0c;名为“ Cobertura”。 该框架与我们在另一篇文章中看到的Emma框架具有相同的功能。 Cobertura和Emma之间的主要区别在于Cobertura显示带有图形的简历页面。 如果要查看有关此…

摇杆控制方向原理_图文全面讲解多种方向控制阀的原理和区别....

液压阀是用来控制液压系统中油液的流动方向或调节其流量和压力的。方向控制阀作为液压阀的一种&#xff0c;利用流道的更换控制着油液的流动方向单向型方向控制阀是只允许气流沿一个方向流动的方向控制阀&#xff0c;如单向阀、梭阀、双压阀等换向型方向控制阀是可以改变气流流…

原型设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

laravel 控制器中使用中间件_在 Laravel 中使用 Slack 进行异常通知

php中文网最新课程每日17点准时技术干货分享异常处理是软件开发过程中无法逃避的问题。对于一套设计良好代码高效的程序&#xff0c;出现异常的可能性会比较低&#xff0c;但这并不意味着不会出现异常,有些异常甚至会引起严重的后果&#xff0c;所以如何及时的发现程序中的异常…

[转]ListView学习笔记(一)——缓存机制

要想优化ListView首先要了解它的工作原理&#xff0c;列表的显示需要三个元素&#xff1a;ListView、Adapter、显示的数据&#xff1b; 这里的Adapter就是用到了适配器模式&#xff0c;不管传入的是什么View在ListView中都能显示出来。 下面简单说下上图的原理&#xff1a; 1、…

golang反编译_【Golang】脱胎换骨的defer(一)

Go语言的defer是一个很方便的机制&#xff0c;能够把某些函数调用推迟到当前函数返回前才实际执行。我们可以很方便的用defer关闭一个打开的文件、释放一个Redis连接&#xff0c;或者解锁一个Mutex。而且Go语言在设计上保证&#xff0c;即使发生panic&#xff0c;所有的defer调…

cad填充图案乱理石_CAD软件中如何自定义CAD填充图案?

在使用浩辰CAD软件绘制完成图纸后&#xff0c;发现自己绘制的CAD图纸没有做好区域分割&#xff0c;显得特别乱。这个时候该怎么办呢&#xff1f;快试试CAD填充图案吧&#xff01;接下来就由小编来给大家介绍一下浩辰CAD软件中自定义CAD填充图案的操作教程吧&#xff01;浩辰CAD…

单例设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

ansi编码转换_8b/1b编码是个什么东东

使用串行比并行总线可以节省更多的布线空间&#xff0c;芯片、电缆等的尺寸可以做得更小&#xff0c;同时传输速率更高。但是&#xff0c;在很多数字系统如CPU、DSP、FPGA等内部&#xff0c;进行数据处理的最小单位都是Byte&#xff0c;即8个bit&#xff0c;如何把一个或多个By…

使用CSDN云服务搭建一个WordPress 个人站点(详细教程)

目录 前言 站点效果图 搭建服务的一些准备工作 第一步。进入到云服务我的账号模块&#xff0c;创建一个项目&#xff0c; 第二步&#xff0c;先免费领取一台云主机&#xff0c; 第三步&#xff0c;进入云主机控制台 搭建站点操作步骤 第一步&#xff0c;登录云主机 第二…

使用CSDN云服务搭建一个WordPress 个人站点(视频教程)

目录 前言 视频教程 文字版教程 云主机体验地址 官方文档 前言 六一儿童节体验了一下CSDN云主机相关的服务&#xff0c;感觉最近官方最近变化很大&#xff0c;业务范围很广&#xff0c;这里简单体验了一下云主机&#xff0c;给大家分享一点心得&#xff0c;希望对大家有所启…

石板切割问题c语言_岩知识 | 岩板切板有讲究,工艺问题要注意

岩板的火继续烧着&#xff0c;岩板的深加工厂在不断地增加着&#xff0c;岩板的深加工产品正在走向各个建筑项目&#xff0c;逐渐在受到很多项目的宠爱。岩板作为与天然石材完全不同的产品&#xff0c;其优越的理化性能在许多方面胜过天然石材&#xff0c;但也有其严重的不足。…

JavaScript测验题回顾-刷题笔记001

目录 1.我们可以在下列哪个 HTML 元素中放置 Javascript 代码&#xff1f;​编辑 2.写 "Hello World" 的正确 Javascript 语法是&#xff1f; 3.插入 Javacript 的正确位置是&#xff1f; 4.引用名为 "xxx.js" 的外部脚本的正确语法是&#xff1f; 5.如…

java 方法委托托管_Java Web托管选项流程图

java 方法委托托管我经常被问到的一个问题是在何处以及如何托管Java Web应用程序。 在带有嵌入式服务器的Eclipse中创建它很好&#xff0c;但是如何将它带给人们呢&#xff1f; 长期以来&#xff0c;对于发烧友的程序员一直没有答案。 只有昂贵和超大型的选择。 事情最近发生了…

react重新渲染菜单_React实现递归组件

前言今天来实现一个 React 的递归组件。具体的效果图如下:图片说明假设后端返回的数据如下&#xff1a;[{ id: 1, parent_id: 0, name: 广东省, children: [{ id: 2, parent_id: 1, name: 广州市, …

JavaScript测验——给代码添加注释---第一关

校验规则 创建一个//样式的注释, 被注释的文本至少要包含 5 个字符。 创建一个/* */样式的注释, 被注释的文本至少要包含 5 个字符。

举重设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …