笨蛋学设计模式行为型模式-解释器模式【23】
行为型模式-解释器模式
- 8.10解释器模式
- 8.10.1概念
- 8.10.2场景
- 8.10.3优势 / 劣势
- 8.10.4解释器模式可分为
- 8.10.5解释器模式
- 8.10.6实战
- 8.10.6.1题目描述
- 8.10.6.2输入描述
- 8.10.6.3输出描述
- 8.10.6.4代码
- 8.10.7总结
8.10解释器模式
8.10.1概念
解释器模式用于定义一个语言的文法规则,并解释和执行该语言中的表达式。它通过将语言表达式表示为一个抽象语法树,并提供解释器来遍历和执行该语法树,从而实现对语言的解释和执行
8.10.2场景
例如编译器将源代码作为输入,通过词法分析和语法分析,构建抽象语法树(AST)。然后编译器使用解释器模式来遍历和执行这个抽象语法树,将源代码转换为机器码,并执行该机器码。
8.10.3优势 / 劣势
- 抽象语法树使得算法独立于语法:抽象语法树作为构建解析器的结构,使得解析器的结构和实现与输入的文本语法无关
- 易于单独扩展:由于解析器和语法规则分别通过抽象语法树和上下文无关文本来表示,因此易于单独扩展
- 抽象语法树复杂:若语法规则非常复杂,抽象语法树可能会变得非常大和复杂,可能导致解析器实现和维护变得困难
- 性能不如基于字符的解析器:由于抽象语法树和上下文无关文本都需要存储和解析
8.10.4解释器模式可分为
- 抽象表达式AbstractExpression:定义了解释器的接口,包含了解释器的方法interpret
- 终结符表达式TerminalExpressio:在语法中不能再分解为更小单元的符号
- 非终结符表达式Non-terminalExpression:文法中的复杂表达式,它由终结符和其他非终结符组成
- 上下文Context:包含解释器之外的一些全局信息,可以存储解释器中间结果,也可以用于向解释器传递信息
8.10.5解释器模式
package com.technologystatck.designpattern.mode.interpreter;public class Interpreters {public static void main(String[] args) {Context context = new Context();Expression expression = new AddException(new TerminalExpression(1), new TerminalExpression(2));int resulult = expression.interpret();System.out.println("Result:"+resulult);System.out.println("Context的全局变量:"+Context.CONTEXTSTR);}
}//创建抽象表达式接口:定义解释器的接口,
//声明一个interpret方法,用于解释语言中的表达式
//抽象表达式接口
interface Expression {int interpret();
}//创建具体的表达式类:实现抽象表达式接口,
//用于表示语言中的具体表达式
class TerminalExpression implements Expression{private int value;public TerminalExpression(int value) {this.value = value;}@Overridepublic int interpret() {return value;}
}//非终结符表达式:抽象表达式的一种,
//用于表示语言中的非终结符表达,通常包含其他表达式
class AddException implements Expression{private Expression left;private Expression right;public AddException(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret()+right.interpret();}
}//上下文:包含解释器需要的一些全局信息或状态
class Context{//可以在上下文中存储一些全局信息或状态public static final String CONTEXTSTR="contextStr";
}
8.10.6实战
8.10.6.1题目描述
小明正在设计一个计算器,用于解释用户输入的简单数学表达式,每个表达式都是由整数、加法操作符+、乘法操作符组成的,表达式中的元素之间用空格分隔,请你使用解释器模式帮他实现这个系统。
8.10.6.2输入描述
每行包含一个数学表达式,表达式中包含整数、加法操作符(+)和乘法操作符(*)。 表达式中的元素之间用空格分隔。
8.10.6.3输出描述
对于每个输入的数学表达式,每行输出一个整数,表示对应表达式的计算结果。
8.10.6.4代码
package com.technologystatck.designpattern.mode.interpreter;import java.util.Scanner;
import java.util.Stack;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Context context = new Context();//处理用户输入的数学表达式while (scanner.hasNextLine()) {String userInput = scanner.nextLine();Expression expression = parseExpression(userInput);if (expression != null) {//将表达式入栈context.pushExpression(expression);System.out.println(expression.interpret());} else {System.out.println("Invalid expression.");}}}//用于解析用户输入的数学表达式并返回相应的抽象表达式类private static Expression parseExpression(String userInput) {try {//定义一个表达式栈Stack<Expression> expressionStack = new Stack<>();//将用户输入的字符串转换为字符数组,方便处理。char[] tokens = userInput.toCharArray();//随意设置一个符号,//主要判断有没有识别进正确的+、*char operator='!';//遍历字符数组,处理字符串。for (int i = 0; i < tokens.length; i++) {char token = tokens[i];if (Character.isDigit(token)) {//将数字传入进去expressionStack.push(new NumberExpression(Character.getNumericValue(token)));//若栈中有两个以上的元素,说明可以进行运算if (i + 1 <= tokens.length && expressionStack.size() >= 2) {Expression right = expressionStack.pop();Expression left = expressionStack.pop();//若有匹配上的,则直接入栈if (operator == '+') {expressionStack.push(new AddException(left, right));} else if (operator == '*') {expressionStack.push(new MulException(left, right));}else{System.out.println("符号有误");}i++; //跳过下一个字符,因为已经处理过了}}else{//若不为数字,就进入这里,将符号赋给操作变量operator=token;}}//返回最后一个元素,即最终的表达式。return expressionStack.pop();} catch (Exception e) {return null;}}
}//创建抽象表达式接口
interface Expression {int interpret();
}//创建终结符表达式类,实现抽象表达式接口
class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}@Overridepublic int interpret() {return number;}
}//创建非终结符表达式加法
class AddException implements Expression {private Expression left;private Expression right;public AddException(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() + right.interpret();}
}//创建非终结符表达式乘法
class MulException implements Expression {private Expression left;private Expression right;public MulException(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() * right.interpret();}
}//上下文类
class Context {//用于存储表达式private Stack<Expression> expressionStack = new Stack<>();//将给定的表达式入栈public void pushExpression(Expression expression) {expressionStack.push(expression);}//从栈顶弹出并返回一个表达式public Expression popExpression() {return expressionStack.pop();}}
8.10.7总结
- 优点:可以实现复杂的语法分析功能,同时解析器和语法规则易于单独扩展
- 总结:就是通过自己定义独立的抽象语法树,使用抽象表达式用于定义解释器的接口、终结符表达式用于定义符号、非终结符表达式包含终结符和非终结符用于存储解释器结果或者向解释器传递信息、上下文来完成解释器的功能
- 场景:需要解释和执行特定领域或业务规则的语言时
相关文章:
笨蛋学设计模式行为型模式-解释器模式【23】
行为型模式-解释器模式 8.10解释器模式8.10.1概念8.10.2场景8.10.3优势 / 劣势8.10.4解释器模式可分为8.10.5解释器模式8.10.6实战8.10.6.1题目描述8.10.6.2输入描述8.10.6.3输出描述8.10.6.4代码 8.10.7总结 8.10解释器模式 8.10.1概念 解释器模式用于定义一个语言的文法…...

SAP ABAP SUBMIT常用用法
导语:一直对SUBMIT的用法模模糊糊,每次用都要去查询,本次痛下决心,腾出时间,梳理了一下,如果本文对你有帮助,点个赞再走~ 之前分享过SUBMIT调用程序获取内表的值,就不重…...
GitLab备份与恢复测试(基于Docker)
GitLab环境准备 docker run --name gitlab \ -p 2022:22 -p 2080:80 -p 2443:443 -d \ -v /opt/gitlab/config:/etc/gitlab \ -v /opt/gitlab/gitlab/logs:/var/log/gitlab \ -v /opt/gitlab/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:16.2.1-ce.0备份 1.修改配置文件…...
android studio开发的一些问题
1、编译后,输出日志乱码 Help-->Edit Custom VM Options...-->-Dfile.encodingUTF-8 2、编译时,出现:connect timed out 试过很多方法啦,都是不行的。最后我自己摸索出方法。 [1]android studio-->Project-->Grad…...
辞职对于我来说,不可避免(10)
人,从有辞职的想法,再到把辞职出口要多久,一天、一星期还是一个月 “别以为我不知道你搞了什么小动作,以后别瞎搞,不然我不客气”,从老板说出来这句话开始,这家公司我注定不可能再待下去。 我很诧异,小蔡刚离职,公司干活的技术就我一个,况且我也没哪里得罪你,你冒出…...

【Java】--网络编程:基于TCP协议的网络通信
【Java】–网络编程:基于TCP协议的网络通信 文章目录 【Java】--网络编程:基于TCP协议的网络通信一、TCP协议1.1 概念1.2 三次握手1.2.1 文字描述1.2.2 画图演示 1.3 四次挥手1.3.1 文字描述1.3.2 画图演示 二、基于TCP的Socket网络编程2.1 概念2.2 服务…...

CMake+QT+大漠插件的桌面应用开发(QThread)
文章目录 CMakeQT大漠插件的桌面应用开发(QThread)简介环境项目结构配置编译环境代码 CMakeQT大漠插件的桌面应用开发(QThread) 简介 在CMakeQT大漠插件的桌面应用开发中已经给出了QT配合大漠插件开发桌面应用的样例 不过由于主…...
【笔记】Helm-3 主题-9 Helm高级技术
Helm高级技术 这部分解释说明了使用Helm的各种高级特性和技术。这部分旨在为Helm的高级用户提供高度自定义和操作chart及发布的信息。每个高级特性都会有它自己的权衡利弊, 因此每个使用它们的都要有Helm的深度知识并小心使用。或者换言之,谨记 Peter Pa…...

YOLOv5改进 | 主干篇 | 华为GhostnetV1一种移动端的专用特征提取网络
一、本文介绍 本文给大家带来的改进机制是华为移动端模型Ghostnetv1,华为GhostnetV1一种移动端的专用特征提取网络,旨在在计算资源有限的嵌入式设备上实现高性能的图像分类。GhostNet的关键思想在于通过引入Ghost模块,以较低的计算成本增加了特征图的数量,从而提高了模型的…...

特斯拉FSD的神经网络(Tesla 2022 AI Day)
这是特斯拉的全自动驾驶(Full Self Driver)技术结构图,图中把自动驾驶模型拆分出分成了几个依赖的模块: 技术底座:自动标注技术处理大量数据,仿真技术创造图片数据,大数据引擎进不断地更新&…...

LLM自回归解码
在自然语言处理(NLP)中,大型语言模型(LLM)如Transformer进行推理时,自回归解码是一种生成文本的方式。在自回归解码中,模型在生成下一个单词时会依赖于它之前生成的单词。 使用自回归解码的公式…...
#Uniapp:uni.request(OBJECT)
uni.request(OBJECT) 发起网络请求。 示例 uni.request({url: https://www.example.com/request, //仅为示例,并非真实接口地址。data: {text: uni.request},header: {custom-header: hello //自定义请求头信息},success: (res) > {console.log(res.data);thi…...

旅游项目day14
其他模块数据初始化 搜索实现 请求一样,但是参数不一样,根据type划分。 后台需要提供一个搜索接口。 请求分发器: 全部搜索 目的地搜索 精确搜索、无高亮展示 攻略搜索 全文搜索、高亮显示、分页 游记搜搜 用户搜索 丝袜哥...

关于缓存 db redis local 取舍之道
文章目录 前言一、影响因素二、db or redis or local1.db2.redis3. local 三、redisson 和 CaffeineCache 封装3.1 redisson3.1.1 maven3.1.2 封装3.1.3 使用 3.2 CaffeineCache3.1.1 maven3.1.2 封装3.1.3 使用 总结 前言 让我们来聊一下数据缓存,它是如何为我们带…...

imgaug库图像增强指南(33):塑造【云层】效果的视觉魔法
引言 在深度学习和计算机视觉的世界里,数据是模型训练的基石,其质量与数量直接影响着模型的性能。然而,获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此,数据增强技术应运而生,成为了解决这一问题的…...
树莓派ubuntu:CSI接口摄像头安装驱动程序及测试
树莓派中使用OV系列摄像头,网上能搜到的文章资源太老了,文章中提到的摄像头配置选项在raspi-config中并不存在。本文重新测试整理树莓派摄像头的驱动安装、配置、测试流程说明。 libcamera 新版本中使用libcamera作为摄像头驱动程序。 libcamera是一个…...
Webpack5入门到原理6:处理图片资源
处理图片资源 过去在 Webpack4 时,我们处理图片资源通过 file-loader 和 url-loader 进行处理 现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源 1. 配置 const path require("path");modul…...
大语言模型(LLM)有哪些?
国际大语言模型 目前国际上有以下几个知名的大语言模型: GPT-4 GPT-4由OpenAI团队开发,是闭源的。GPT(Generative Pre-trained Transformer)系列是目前最著名的大语言模型之一。最早的版本是GPT-1,之后发展到了GPT-2和GPT-3&…...

2 - 部署Redis集群架构
部署Redis集群架构 部署Redis集群部署管理主机第一步 准备ruby脚本的运行环境第二步 创建脚本第三步 查看脚本帮助信息 配置6台Redis服务器第一步 修改配置文件启用集群功能第二步 重启redis服务第三步 查看Redis-server进程状态(看到服务使用2个端口号为成功&#…...

NOIP2003提高组T1:神经网络
题目链接 [NOIP2003 提高组] 神经网络 题目背景 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向&am…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...