18、设计模式之解释器模式(Interpreter)
一、什么是解释器模式
解释器模式是一种行为型设计模式。解释器模式就像是一种自定义语言,我们可以定义该语言的语法规则,然后从中解析出具体的命令或表达式,最终执行相应的操作。
eg:这种模式比较冷门,不怎么使用。
二、角色组成
抽象表达式(Abstract Expression):定义了解释器需要实现的接口。
终止符表达式(Terminal Expression):表示该语言中的终止符(例如,变量、函数等),终止符表达式的解释方法通常很简单,往往只包含一两行代码。
非终止符表达式(Nonterminal Expression):表示该语言中的非终止符(例如,语句块、条件语句、循环语句等),非终止符表达式的解释方法通常需要对内部表达式进行递归调用。
上下文(Context):存储了当前语言解释器的状态信息。
三、优缺点
优点:
扩展性好。由于解释器模式定义了语言的文法,因此可以很容易地添加新的表达式类和解释方法,从而扩展语言的解释能力。
灵活性高。由于解释器模式是基于接口设计的,因此可以很容易地替换解释器的实现或更改其执行方式,从而满足不同的需求。
缺点:
由于解释器模式需要定义很多类和解释方法,因此代码量比较大,实现起来有一定的复杂。度。
对于复杂的表达式,解释器模式的解释器可能需要占用更多的内存空间和运行资源,从而导致程序性能下降。
如果语言的文法非常复杂,解释器模式的实现可能会很困难,而且难以维护和扩展。
四、应用场景
4.1 生活场景
数学表达式求值:我们可以设计一个数学表达式解释器,将数学表达式解释为可计算的结果,从而方便进行运算。
游戏AI:通过解释器来解析AI所需的数据和指令,然后根据这些数据和指令执行相应的行为。
语言翻译:将一种语言的文本解析为另一种语言的文本。翻译器可以将输入的文本解析为一系列的单词、短语和句子,然后通过对这些语言结构进行翻译,将其转换成目标语言的文本。
4.2 java场景
正则表达式。正则表达式是一种用于描述字符串模式的语言,它可以非常灵活地描述满足特定模式的字符串,因此解释器模式是实现正则表达式的常用方法之一。
SQL解析器。SQL是一种结构化查询语言,用于在关系型数据库中进行数据操作和管理。为了将SQL语句转换为数据库操作,我们需要实现一个SQL解析器,将SQL语句解释为可执行的SQL命令,这就需要使用解释器模式。
java代码:需要编译器进行编译后才能运行,这个编译器就相当于解释器。
五、代码实现
下面以四则运算表达式,来解释一下解释器模式。
抽象表达式:Expression
终止符表达式:Constant、Variable
非终止符表达式:AddExpression、SubExpression
上下文:InterpreterVariables
5.0 UML类图

5.1 Expression——抽象表达式(Abstract Expression)
/**** 1.抽象表达式(Abstract Expression)* 抽象表达式定义了用于解释特定语言的接口。*/
public abstract class Expression {//定义解释器方法public abstract int interpret();
}
5.2 终结符表达式(Terminal Expression)
/*** * 2.终结符表达式(Terminal Expression):变量* 终结符表达式表示语言中的终止符(例如,变量、关键字等)。*/
public class Variable extends Expression{private String name;public Variable(String name) {this.name = name;}@Overridepublic int interpret() {// 从上下文中获取该变量对应的值return InterpreterVariables.getValue(this.name);}
}
/*** * 2.终结符表达式(Terminal Expression):常量* 终结符表达式表示语言中的终止符(例如,变量、关键字等)。*/
public class Constant extends Expression{private int value;public Constant(int value) {this.value = value;}@Overridepublic int interpret() {// 直接返回常量值return value;}
}
5.3 非终结符表达式(Nonterminal Expression)
/*** * 3.非终结符表达式(Nonterminal Expression):加法运算* 非终结符表达式表示语言中的非终止符(例如,语句块、语句等)。*/
public class AddExpression extends 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();}
}
/*** * 3.非终结符表达式(Nonterminal Expression):减法运算* 非终结符表达式表示语言中的非终止符(例如,语句块、语句等)。*/
public class SubExpression extends Expression{private Expression left;private Expression right;public SubExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() - right.interpret();}
}
5.4 InterpreterVariables——上下文(Context)
/*** * 4.上下文(Context):负责存储变量名和其值之间的映射关系* 上下文保存了解释器解释表达式需要的信息。*/
public class InterpreterVariables {private static Map<String, Integer> variables = new HashMap<>();// 根据变量名获取其对应的值public static int getValue(String name) {if(variables.containsKey(name)) {return variables.get(name);}// 默认返回0return 0;}// 设置变量名和其对应的值public static void setValue(String name, int value) {variables.put(name, value);}
}
5.5 testInterpreter
/*** * 解释器模式测试类*/
@SpringBootTest
public class TestInterpreter {@Testvoid testInterpreter(){// 创建变量x、y和常量1,并设置变量x和y的值Variable x = new Variable("x");Variable y = new Variable("y");Constant c = new Constant(1);InterpreterVariables.setValue("x", 10);InterpreterVariables.setValue("y", 5);// 创建解释器表达式(x - y)+ 1Expression expression = new AddExpression(new SubExpression(x, y), c);// 解释表达式,并获取最终结果int result = expression.interpret();System.out.println("计算结果:" + result);}
}

六、总结
解释器是一个简单的语法分析工具,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。因此,尽量不要在重要的模块中使用解释器模式,在项目中可以使用shell、JRuby、Groovy等脚本语言来代替解释器模式,也可以用开源包,比如Express4J、JEP,功能都很强大。
出现以下场景,可以考虑使用(尽量别用,大佬除外):
需要定义一种自定义语言,并对其进行解析和执行。
需要实现一种自定义的文件格式,并对其进行解析和处理。
需要对复杂的数据结构进行解析,并对其进行处理或转换。
需要实现一些自定义的算法或规则,并对其进行解析和执行。
相关文章:
18、设计模式之解释器模式(Interpreter)
一、什么是解释器模式 解释器模式是一种行为型设计模式。解释器模式就像是一种自定义语言,我们可以定义该语言的语法规则,然后从中解析出具体的命令或表达式,最终执行相应的操作。 eg:这种模式比较冷门,不怎么使用。 …...
cpp qt 一个奇怪的bug
今天在用cpp qt的时候发现了一个奇怪的东西 这是我的源代码 #include "mywidget.h" #include <QPushButton>myWidget::myWidget(QWidget *parent): QWidget(parent) {QPushButton * btn1 new QPushButton;btn1->show();btn1->setParent(this);btn1-&g…...
第6章:MATLAB文本数据处理进阶篇的目录 (MATLAB入门课程)
讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。 MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 第6章:MATLAB文本数据处理进阶篇 6.1 文本格式化 …...
软件杯 深度学习 opencv python 公式识别(图像识别 机器视觉)
文章目录 0 前言1 课题说明2 效果展示3 具体实现4 关键代码实现5 算法综合效果6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习的数学公式识别算法实现 该项目较为新颖,适合作为竞赛课题方向,学…...
vscode通过多个跳板机连接目标机(两种方案亲测成功)
1、ProxyJump(推荐使用) 需要OpenSSH 7.3以上版本才可使用,可用下列命令查看: ssh -V ProxyJump命令行使用方法 ssh -J [email protected]:port1,[email protected]:port2 一层跳板机: ssh dst_usernamedst_ip -…...
C++基础复习003
vector去重 第一种,利用set容器的特性进行去重: #include <iostream> #include <vector> #include <set> using namespace std; int main() {vector<int>test{1,2,3,3,3,4,2,3,5,2,63,56,34,24};set<int>s(test.begin(),…...
Docker Commit提交
Docker Commit提交 Docker Commit镜像提交 以一个正在运行的tomcat为例因为docker拉取的镜像都是删减版,所以需要将webapp.dist的文件内容复制到webapps中再将自己制作的镜像放在正在运行服务器上,不是云端服务器上 #进入tomcat,这是一个正…...
百度现在应该怎么去做搜索SEO优化?(川圣SEO)蜘蛛池
baidu搜索:如何联系八爪鱼SEO? baidu搜索:如何联系八爪鱼SEO? baidu搜索:如何联系八爪鱼SEO? 百度搜索引擎优化(SEO)是一种通过优化网站,提升网页在百度搜索结果中的排…...
登录凭证------
为什么需要登录凭证? web开发中,我们使用的协议http是无状态协议,http每次请求都是一个单独的请求,和之前的请求没有关系,服务器就不知道上一步你做了什么操作,我们需要一个办法证明我没登录过 制作登录凭…...
matplotlib系统学习记录
日期:2024.03.12 内容:将matplotlib的常用方法做一个记录,方便后续查找。 基本使用 # demo01 from matplotlib import pyplot as plt # 设置图片大小,也就是画布大小 fig plt.figure(figsize(20,8),dpi80)#图片大小,清晰度# 准…...
【DL】ML系统学习笔记 1
【DL】ML系统学习笔记 1 1. 机器学习定义2. 机器学习三大任务3. 机器学习定义回归举例4. Gradient Descent 优化5. Gradient Descent 优化步骤6. 回归步骤小姐7. Linear models8. 核心步骤流程9. 模型优化9. 深度学习引出1. 机器学习定义 Machine Learning Looking for Functio…...
ffmpeg视频处理常用命令
1.ffmpeg主要参数 -f fmt(输入/输出) 强制输入或输出文件格式。 格式通常是自动检测输入文件, 并从输出文件的文件扩展名中猜测出来,所以在大多数情况下这个选项是不需要的。-i url(输入) 输入文件的网址-…...
前端npm和yarn更换国内淘宝镜像
NPM 查询当前镜像 npm get registry 设置为淘宝镜像 npm config set registry https://registry.npm.taobao.org/ (旧地址) npm config set registry https://registry.npmmirror.com/ (最新地址) 设置为官方镜像 npm config set registry https://registry.n…...
华为配置OSPF的Stub区域示例
配置OSPF的Stub区域示例 组网图形 图1 配置OSPF Stub区域组网图 Stub区域简介配置注意事项组网需求配置思路操作步骤配置文件 Stub区域简介 Stub区域的ABR不传播它们接收到的自治系统外部路由,在Stub区域中路由器的路由表规模以及路由信息传递的数量都会大大减少…...
学会Web UI框架--Bootstrap,快速搭建出漂亮的前端界面
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 所属的专栏:前端泛海 景天的主页:景天科技苑 文章目录 Bootstrap1.Bootstrap介绍2.简单使用3.布局容器4.Bootstrap实现轮播…...
C语言学习大纲
笔者看了下某二本的C语言考研大纲,供平常学习参考,主要考察知识点: C语言概述 (1) 了解程序设计语言的语法 (2) 掌握C语言的特点 (3) 掌握问题求解的过程数据描述 (1&am…...
Unity URP 如何写基础的曲面细分着色器
左边是默认Cube在网格模式下经过曲面细分的结果,右边是原状态。 曲面细分着色器在顶点着色器、几何着色器之后,像素着色器之前。 它的作用时根据配置信息生成额外的顶点以切割原本的面片。 关于这部分有一个详细的英文教程,感兴趣可以看一…...
android pdf框架-8,图片缓存
解码会产生很多图片,滑过后不要显示,如果直接回收,会浪费不少资源. 在没有缓存的情况下,会看到gc还是比较频繁的. 有了缓存后,明显gc少了. 目录 常用的缓存 自定义缓存 显示相关的内存缓存 解码缓存池 内存缓存实现: 解码缓存池实现: 常用的缓存 lrucache,这是最常用…...
UE5.2 SmartObject使用实践
SmartObject是UE5新出的一项针对AI的功能,可为开发者提供如公园长椅、货摊等交互对象的统一外观封装,如UE的CitySample(黑客帝国Demo)中就运用到了SmartObject。 但SmartObject实践起来较为繁琐,主要依赖于AI及行为树…...
奇舞周刊第521期:实现vue3响应式系统核心-MVP 模型
奇舞推荐 ■ ■ ■ 实现vue3响应式系统核心-MVP 模型 手把手带你实现一个 vue3 响应式系统,代码并没有按照源码的方式去进行组织,目的是学习、实现 vue3 响应式系统的核心,用最少的代码去实现最核心的能力,减少我们的学习负担&…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
