设计模式之解释器模式(上)
解释器模式
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年前景预测如下: 市场需求持续增长:随着全球对节能减排和绿色建筑…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...