设计模式之解释器模式(上)
解释器模式
1)概述
1.定义
定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。
2.结构图

3.角色
AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。
TerminalExpression(终结符表达式):它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例,通常在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。
NonterminalExpression(非终结符表达式):它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。
注意:
在解释器模式中,每一种终结符和非终结符都有一个具体类与之对应,正因为使用类来表示每一条文法规则,所以系统将具有较好的灵活性和可扩展性。
4.代码实现
抽象表达式类
abstract class AbstractExpression {public abstract void interpret(Context ctx);
}
终结符表达式
public class TerminalExpression extends AbstractExpression {public void interpret(Context ctx) {//终结符表达式的解释操作}
}
非终结符表达式
public class NonterminalExpression extends AbstractExpression {private AbstractExpression left;private AbstractExpression right;public NonterminalExpression(AbstractExpression left,AbstractExpression right) {this.left=left;this.right=right;}public void interpret(Context ctx) {//递归调用每一个组成部分的interpret()方法//在递归调用时指定组成部分的连接方式,即非终结符的功能}
}
环境类
public class Context {private HashMap map = new HashMap();public void assign(String key, String value) {//往环境类中设值}public String lookup(String key) {//获取存储在环境类中的值}
}
2)完整解决方案
1.解释过程-抽象语法树

2.结构图

AbstractNode充当抽象表达式角色,DirectionNode、ActionNode和DistanceNode充当终结符表达式角色,AndNode和SentenceNode充当非终结符表达式角色。
3.代码实现
抽象表达式
//抽象表达式
abstract class AbstractNode {public abstract String interpret();
}
非终结符表达式
//And解释:非终结符表达式
public class AndNode extends AbstractNode {private AbstractNode left; //And的左表达式private AbstractNode right; //And的右表达式public AndNode(AbstractNode left, AbstractNode right) {this.left = left;this.right = right;}//And表达式解释操作public String interpret() {return left.interpret() + "再" + right.interpret();}
}//简单句子解释:非终结符表达式
public class SentenceNode extends AbstractNode {private AbstractNode direction;private AbstractNode action;private AbstractNode distance;public SentenceNode(AbstractNode direction, AbstractNode action, AbstractNode distance) {this.direction = direction;this.action = action;this.distance = distance;}//简单句子的解释操作public String interpret() {return direction.interpret() + action.interpret() + distance.interpret();}
}
终结符表达式
//方向解释:终结符表达式
public class DirectionNode extends AbstractNode {private String direction;public DirectionNode(String direction) {this.direction = direction;}//方向表达式的解释操作public String interpret() {if (direction.equalsIgnoreCase("up")) {return "向上";} else if (direction.equalsIgnoreCase("down")) {return "向下";} else if (direction.equalsIgnoreCase("left")) {return "向左";} else if (direction.equalsIgnoreCase("right")) {return "向右";} else {return "无效指令";}}
}//动作解释:终结符表达式
public class ActionNode extends AbstractNode {private String action;public ActionNode(String action) {this.action = action;}//动作(移动方式)表达式的解释操作public String interpret() {if (action.equalsIgnoreCase("move")) {return "移动";} else if (action.equalsIgnoreCase("run")) {return "快速移动";} else {return "无效指令";}}
}//距离解释:终结符表达式
public class DistanceNode extends AbstractNode {private String distance;public DistanceNode(String distance) {this.distance = distance;}//距离表达式的解释操作public String interpret() {return this.distance;}
}
工具类InstructionHandler用于对输入指令进行处理,将输入指令分割为字符串数组,将第1个、第2个和第3个单词组合成一个句子,并存入栈中;如果发现有单词“and”,则将“and”后的第1个、第2个和第3个单词组合成一个新的句子作为“and”的右表达式,并从栈中取出原先所存句子作为左表达式,然后组合成一个And节点存入栈中,依此类推,直到整个指令解析结束。
import java.util.Stack;//指令处理类:工具类
public class InstructionHandler {private AbstractNode node;public void handle(String instruction) {AbstractNode left = null, right = null;AbstractNode direction = null, action = null, distance = null;//声明一个栈对象用于存储抽象语法树Stack stack = new Stack();//以空格分隔指令字符串String[] words = instruction.split(" ");for (int i = 0; i < words.length; i++) {if (words[i].equalsIgnoreCase("and")) {//弹出栈顶表达式作为左表达式left = (AbstractNode) stack.pop();String word1 = words[++i];direction = new DirectionNode(word1);String word2 = words[++i];action = new ActionNode(word2);String word3 = words[++i];distance = new DistanceNode(word3);right = new SentenceNode(direction, action, distance); //右表达式stack.push(new AndNode(left, right)); //将新表达式压入栈中} else {//如果是从头开始进行解释,则将前三个单词组成一个简单句子SentenceNode并将该句子压入栈中String word1 = words[i];direction = new DirectionNode(word1);String word2 = words[++i];action = new ActionNode(word2);String word3 = words[++i];distance = new DistanceNode(word3);left = new SentenceNode(direction, action, distance);//将新表达式压入栈中stack.push(left);}}this.node = (AbstractNode) stack.pop(); //将全部表达式从栈中弹出}public String output() {return node.interpret();}
}
客户端类
public class Client {public static void main(String[] args) {String instruction = "up move 5 and down run 10 and left move 5";InstructionHandler handler = new InstructionHandler();handler.handle(instruction);String outString;outString = handler.output();System.out.println(outString);}
}
相关文章:
设计模式之解释器模式(上)
解释器模式 1)概述 1.定义 定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。 2.结构图 3.角色 AbstractExpression(抽象表达式):在抽象表达…...
[23年蓝桥杯] 买二赠一
题目描述 【问题描述】 某商场有 N 件商品,其中第 i 件的价格是 A i 。现在该商场正在进行 “ 买二 赠一” 的优惠活动,具体规则是: 每购买 2 件商品,假设其中较便宜的价格是 P (如果两件商品价格一样, 则…...
PgSQL的with as语法
returning 返回的这一些字段,然后进行汇总为remove_alarms 然后select一下remove_alarms 出来的数据然后保存到tb_alarm_his 里面 with remove_alarms as( delete fromtb_alarm whereid in (508) returning 0,now(),admin,alarmadvice,alarmadvicecn,alarmarises…...
六、c++代码中的安全风险-fopen
(misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). 为…...
uniapp项目问题及解决(前后端互联)
1.路由跳转的问题 uni.navigateTo() 保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面 uni.redirectTo() 关闭当前页面,跳转到应用内的某个页面。 uni.reLaunch&…...
面试算法-154-搜索二维矩阵 II
题目 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例 1: 输入:matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,…...
Java中Stream流介绍
Java 8引入的Stream API是Java中处理集合的一种高效方式,它提供了一种高级的迭代方式,允许你以声明式方式处理数据。Stream API可以对数据执行复杂的查询操作,而不需要编写冗长且复杂的循环语句。下面是一些使用Stream API的常见场景和示例&a…...
深度学习的层、算子和函数空间
目录 一、层、算子和函数空间概念 二、层(Layers) 三、算子(Operators) 3.1常见算子 3.2常见算子的性质 四、函数空间(Function Space) 一、层、算子和函数空间概念 层(Layers)…...
Pillow教程11:九宫格切图的实现方法(安排!!!)
---------------Pillow教程集合--------------- Python项目18:使用Pillow模块,随机生成4位数的图片验证码 Python教程93:初识Pillow模块(创建Image对象查看属性图片的保存与缩放) Pillow教程02:图片的裁…...
Macos 部署自己的privateGpt(2024-0404)
Private Chatgpt 安装指引 https://docs.privategpt.dev/installation/getting-started/installation#base-requirements-to-run-privategpt 下载源码 git clone https://github.com/imartinez/privateGPT cd privateGPT安装软件 安装: Homebrew /bin/bash -c…...
先安装CUDA后安装Visual Studio的额外配置
VS新建项目中增加CUDA选项 以vs2019 cuda 11.3为例 关闭vs2019解压cuda的windows安装包cuda_11.3.0_465.89_win10.exe进入路径cuda_11.3.0_465.89_win10\visual_studio_integration\CUDAVisualStudioIntegration\extras\visual_studio_integration\CudaProjectVsWizards\拷贝…...
2024 蓝桥打卡Day35
20240407蓝桥杯备赛 1、学习蓝桥云课省赛冲刺课 【3-搜索算法】【4-枚举与尺度法】2、学习蓝桥云课Java省赛无忧班 【1-语言基础】3、代码练习数字反转数字反转优化算法sort排序相关String字符串相关StringBuilder字符串相关HashSet相关 1、学习蓝桥云课省赛冲刺课 【3-搜索算法…...
【Java】单例模式
单例模式是面试中常考的设计模式之一 在面试中,面试官常常会要求写出两种类型的单例模式并解释原理 本文中,将从0到1的介绍单例模式究竟是什么 文章目录 ✍一、什么是设计模式?✍二、单例模式是什么?✍三、单例模式的类型**1.饿汉…...
Linux|从 STDIN 读取 Awk 输入
简介 在之前关于 Awk 工具的系列文章中,主要探讨了如何从文件中读取数据。但如果你希望从标准输入(STDIN)中读取数据,又该如何操作呢? 在本文中,将介绍几个示例,展示如何使用 Awk 来过滤其他命令…...
关于K8S集群中maste节点r和worker节点的20道面试题
1. 什么是Kubernetes(K8S)? Kubernetes(通常简称为K8S)是一种开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是Kubernetes的一些核心特性和优势: 自动化部署和扩展&…...
基于 OpenHarmony HistogramComponent 柱状图开发指南
1. HistogramComponent 组件功能介绍 1.1. 功能介绍 应用开发过程,用鸿蒙提供的 Component 自定义柱状图效果。 HistogramComponent 组件可以更快速实现一个简单的柱状图功能。 HistogramComponent 对外提供数据源,修改柱状图颜色,间距的…...
C语言指针相关
C语言指针int(*p)[4]如何理解? 快速搞懂 C/C 指针声明...
设计模式:责任链模式
责任链模式是一种行为设计模式,允许你将请求沿着一条链传递,直到一个对象处理它为止。这种模式包含了一些处理对象,每个对象都包含逻辑来处理特定类型的命令或请求。如果一个对象不能处理该请求,它就会将请求传递给链中的下一个对象,如此类推。 定义 责任链模式通过定义…...
【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.6p1(亲测无问题,建议收藏)
👨🎓博主简介 🏅CSDN博客专家 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入!…...
宁波中墙建材对于蒸压加气混凝土砌块2024年前景预测
宁波中墙建材对于蒸压加气混凝土砌块2024年前景预测 蒸压加气混凝土砌块(AAC)是一种轻质、多孔、保温隔热性能良好的建筑材料,广泛应用于建筑领域。2024年前景预测如下: 市场需求持续增长:随着全球对节能减排和绿色建筑…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
