设计模式----解释器模式

一、简介

        解释器模式使用频率并不高,通常用来构建一个简单语言的语法解释器,它只在一些非常特定的领域被用到,比如编译器、规则引擎、正则表达式、sql解析等。

        解释器模式是行为型设计模式之一,它的原始定义为:用于定义语言语法规则表示,并提供解释器来处理句子中的语法。

        我们通过一个例子来解释下解释器模式,假设我们设计一个软件来进行加减计算,我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。

public int add(int a,int b){
return a+b;
}public int add(int a,int b,int c){
return a+b+c;
}
......

上面的形式比较单一、有限如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符数组可以有无限种合作方式,比如1+3+2+1-5....

        解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。

二、结构

        解释器模式由以下几种角色组成:

        ①抽象表达式角色:定义解释器的接口,约定解释器的操作,主要包含解释方法interoret

        ②终结符表达式角色:用来实现文发中与终结符相关的操作,文法中的每一个终结符都有一个具体的终结符表达式与之对应

        ③非终结符表达式:用来实现文法中与非终结符相关的操作,文法中每条规则都对应一个非终结符表达式

        ④上下文类:通常包含各个解释器需要的数据或者是公共的功能,一般用来传递所有解释器共享的数据。

三、实现

        我们定义一个进行加减乘除计算的语言,语法规则如下:

        ①运算符只包含加减乘除,并且没有优先级概念

        ②表达式中,先写数字后写运算符,空格隔开

// 表达式接口
public interface Expression {int interpret();
}// 加法解释器
public class AddExpression implements Expression {private Expression left;private Expression right;public AddExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() + right.interpret();}
}// 减法解释器
public class SubtractExpression implements Expression {private Expression left;private Expression right;public SubtractExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() - right.interpret();}
}// 乘法解释器
public class MultiplyExpression implements Expression {private Expression left;private Expression right;public MultiplyExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() * right.interpret();}
}// 除法解释器
public class DivideExpression implements Expression {private Expression left;private Expression right;public DivideExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {try {return left.interpret() / right.interpret();} catch (ArithmeticException e) {System.out.println("除数不能为0");return -1;}}
}// 数字解释器
public class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}@Overridepublic int interpret() {return number;}
}

现在我们可以使用这些类来解析四则运算表达式了。例如,对于表达式 “1 + 2 * 3 - 4 / 2”我们可以使用以下代码来解析该表达式:

Expression expression = new SubtractExpression(new AddExpression(new NumberExpression(1),new MultiplyExpression(new NumberExpression(2),new NumberExpression(3))),new DivideExpression(new NumberExpression(4),new NumberExpression(2)));
int result = expression.interpret();
System.out.println("计算结果为:" + result);

四、总结

优点

①易于改变可扩展文法,因为在解释器模式中实用类来表示语言的文法规则的,因此可以通过继承等机制改变或扩展文法,每一个文法规则都可以表示为一个类,因此我们可以快速的实现一个迷你的语言

②实现文法比较容易,在抽像语法术中每一个表达式节点的实现方式都是相似的,这些代码不特别复杂

③增加新的解释表达式比较方便,如果用户增加新的解释表达式,只需要对应增加一个新的表达式类就可以,原有的表达式不需修改,符合开闭原则

缺点

①对于复杂文法难以维护,在解释器中,一条规则至少要定义一个类,因此一个语言中有太多的文法规则,那么就会使类的个数急剧增加,导致系统的维护难以管理。

②执行效率低,在解释器模式中,大量的使用循环和递归调用,所以复杂的句子执行起来比较繁琐

使用场景

①当语言的文法比较简单时,并且执行的效率不是关键问题的时候

②当问题重复出现,且可以用一种简单的语言来表达

③当一个语言要解释执行,并且语言中的句子可以表示为一个抽象的语法树的时候。

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

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

相关文章

SSTI模板注入基础(Flask+Jinja2)

文章目录 一、前置知识1.1 模板引擎1.2 渲染 二、SSTI模板注入2.1 原理2.2 沙箱逃逸沙箱逃逸payload讲解其他重要payload 2.3 过滤绕过点.被过滤下划线_被过滤单双引号 "被过滤中括号[]被过滤关键字被过滤 三、PasecaCTF-2019-Web-Flask SSTI参考文献 一、前置知识 1.1 模…

Linux(一)Linux理论

文章目录 一、Linux概述1.1 体系结构1.1.1 Linux内核1.1.2 用户态与内核态1.1.3 交换空间1.1.4 CLI和GUI 1.2 开机启动过程1.3 系统运行级别1.4 Linux进程1.4.1 Linux进程通信的方法1.4.2 Linux进程状态 二、文件2.1 Linux文件系统2.2 目录结构2.3 绝对路径和相对路径2.4 日志文…

刷题第五十一天 84. 柱状图中最大矩形

好难,看解析: # 双指针 class Solution:def largestRectangleArea(self, heights: List[int]) -> int:size len(heights)# 两个DP数列储存的均是下标indexmin_left_index [0] * sizemin_right_index [0] * sizeresult 0# 记录每个柱子的左侧第一…

量化投资策略的评估标准及其计算公式

收益率指标:分为策略的总收益率和策略的年化收益率 策略的总收益率: 策略的总收益率是评价一个策略盈利能力的最基本的指标,其计算方法为: 公式中Vt表示策略最终的股票和现金的总价值,V0表示策略最初的股票和现金的总…

prometheus二进制安装

1、在需要安装prometheus的目录下执行wget命令下载软件到本地,如我的路径是/opt/module/prometheus wget https://github.com/prometheus/prometheus/releases/download/v2.34.0/prometheus-2.34.0.linux-amd64.tar.gz正在解析主机 objects.githubusercontent.com …

1.关于浏览器

一、认识主流浏览器 Chrome谷歌浏览器Safari苹果浏览器Firefox火狐浏览器Opera欧朋浏览器 二、浏览器内核是什么? 三、五大浏览器,四大内核 四、前端做网页开发用什么浏览器? Chrome谷歌浏览器。

04_线性表

线性表 顺序表顺序表的实现顺序表的遍历顺序表的容量可变顺序表的时间复杂度java中ArrayList实现 链表单向链表单向链表API设计java中LinkedList实现 链表的复杂度分析链表反转快慢指针中间值问题单向链表是否有环问题有环链表入口问题 循环链表约瑟夫问题 栈栈概述生活中的栈计…

【FPGA】分享一些FPGA协同MATLAB开发的书籍

在做FPGA工程师的这些年,买过好多书,也看过好多书,分享一下。 后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍【FPGA】分享一些FPGA协同MATLAB开发的书籍 【FPGA】分享一些FPGA视频图像处理相关的书籍 【FPGA】分享一些FPGA高速…

【银行测试】相关专业知识点+核心业务系统性能方法(汇总)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、银行测试相关专…

如何使用kali来进行一次ddos攻击

本文章用于记录自己的学习路线,不用于其他任何途径! ! ! 哈喽啊!又是好久不见,本博主在之前发过一个ddos攻击的介绍。 emm…虽然那篇文章也提到了ddos攻击的方式,但太过于简陋,好像也没有什么用,so&#…

Hadoop入门学习笔记——五、在虚拟机中部署Hive

视频课程地址:https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接:https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记(汇总) 目录 五、在虚拟机中部署Hive5.1. 在node1虚拟机安装MySQL5.2.…

视频编辑与制作,添加视频封面的软件

如今,视频已经成为了我们生活中不可或缺的一部分,无论是社交媒体上的短视频,还是电影、电视剧,视频都以其独特的魅力吸引着我们的目光。而在这背后,视频剪辑软件功不可没。今天,我就为大家揭秘一款新一代的…