当前位置: 首页 > news >正文

解释器模式(Interpreter)

解释器模式是一种行为设计模式,可以解释语言的语法或表达式。给定一个语言,定义它的文法的一种表示,然后定义一个解释器,使用该文法来解释语言中的句子。解释器模式提供了评估语言的语法或表达式的方式。

Interpreter is a behavior design pattern. It can interpret the syntax or expressions of a language. 
Given a language, define a representation of its grammar, and then define an interpreter 
that uses the grammar to interpret sentences by the language.

结构设计

解释器模式包含如下角色:
Context,上下文,包含解释器之外的一些全局信息。
AbstractExpression,抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
TerminalExression,终结符表达式,实现与文法中的终结符相关联的解释操作。
NonterminalExpression,非终结符表达式,实现与文法中的非终结符相关联的解释操作,对文法中每一条规则R1、R2、…、Rn 都需要一个具体的非终结符表达式类。
Client,客户端,构建一个句子,它是TerminalExression和NonterminalExpression的实例的一个抽象语法树,然后初始化Context,并调用解释操作。
解释器模式类图表示如下:
请添加图片描述

伪代码实现

接下来将使用代码介绍下解释器模式的实现。由于无法使用抽象的用例表示出解释器模式,所以这里会基于特定的场景给出代码示例。这里以常见的四则运算(由于除法需要特殊处理,这里暂不提供)的解析为例,
介绍下解释器模式的实现。

// 1、抽象表达式,声明一个抽象的解释操作接口
public interface Expression {int interpret();
}//2、终结符表达式,实现与文法中的终结符相关联的解释操作,这里是数字  
public class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}public NumberExpression(String number) {this.number = Integer.parseInt(number);}@Overridepublic int interpret() {return this.number;}
}// 3、非终结符表达式,实现与文法中的非终结符相关联的解释操作,这里是运算符
public class AdditionExpression implements Expression {private Expression firstExpression, secondExpression;public AdditionExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.addExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "+";}
}
public class SubtractionExpression implements Expression {private Expression firstExpression, secondExpression;public SubtractionExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.subtractExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "-";}
}
public class MultiplicationExpression implements Expression {private Expression firstExpression, secondExpression;public MultiplicationExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic int interpret() {return Math.multiplyExact(this.firstExpression.interpret(), this.secondExpression.interpret());}@Overridepublic String toString() {return "*";}
}// 4、表达式分析器,将输入解析成表达式并执行相关的计算
public class ExpressionParser {private static final String ADD = "+";private static final String SUBTRACT = "-";private static final String MULTIPLY = "*";private static final String SPLITTER = " ";private LinkedList<Expression> stack = new LinkedList();public int parse(String str) {String[] tokenList = str.split(SPLITTER);for (String symbol : tokenList) {if (!isOperator(symbol)) {Expression numberExpression = new NumberExpression(symbol);stack.push(numberExpression);} else {Expression firstExpression = stack.pop();Expression secondExpression = stack.pop();Expression operator = getExpressionObject(firstExpression, secondExpression, symbol);if (operator == null) {throw new RuntimeException("unknown symbol: " + symbol);}int result = operator.interpret();NumberExpression resultExpression = new NumberExpression(result);stack.push(resultExpression);}}return stack.pop().interpret();}private boolean isOperator(String symbol) {return symbol.equals(ADD) || symbol.equals(SUBTRACT) || symbol.equals(MULTIPLY);}private Expression getExpressionObject(Expression firstExpression, Expression secondExpression, String symbol) {switch (symbol) {case ADD:return new AdditionExpression(firstExpression, secondExpression);case SUBTRACT:return new SubtractionExpression(firstExpression, secondExpression);case MULTIPLY:return new MultiplicationExpression(firstExpression, secondExpression);default:return null;}}
}// 5、客户端
public class InterpreterClient {public void test() {// (1) 定义输入String input = "2 1 5 + *";System.out.println("input is: " + input);// (2) 创建表达式分析器实例ExpressionParser expressionParser = new ExpressionParser();// (3) 执行分析操作int result = expressionParser.parse(input);System.out.println("result: " + result);}
}

适用场景

在以下情况下可以考虑使用解释器模式:
(1)如果需要解释执行的语言中的句子,可以表示为一个抽象语法树,可以考虑使用解释器模式。如SQL 解析、符号处理引擎、正则表达式等。
(2) 对于重复出现的问题,如果可以使用简单的语言来表达,可以考虑使用解释器模式。
(3) 一个简单语法需要解释的场景,可以考虑使用解释器模式。对于简单语法,由于其文法规则较简单,使用解释器模式要优于语法分析程序。

优缺点

解释器模式有以下优点:
(1) 可扩展性好。因为该模式使用类来表示文法规则,可以使用继承来改变或扩展该文法。
(2) 易于实现简单的文法。定义抽象语法树各个节点的类的实现大体相似。
但是该模式也存在以下缺点:
(1) 可利用场景比较少。
(2) 对于复杂的文法比较难维护。包含许多规则的文法可能难以管理和维护。
(3) 会引起类膨胀。随着文法规则的复杂化,类的规模也会随之膨胀。
(4) 使用了大量的循环和递归,需要考虑效率问题。

参考

《设计模式 可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英军, 马晓星等译
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/mediator.html 解释器模式
https://refactoringguru.cn/design-patterns/mediator 解释器模式
https://www.runoob.com/design-pattern/mediator-pattern.html 解释器模式
https://www.cnblogs.com/adamjwh/p/10959987.html 简说设计模式——解释器模式
https://springframework.guru/gang-of-four-design-patterns/interpreter-pattern/ Interpreter Pattern

相关文章:

解释器模式(Interpreter)

解释器模式是一种行为设计模式&#xff0c;可以解释语言的语法或表达式。给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;然后定义一个解释器&#xff0c;使用该文法来解释语言中的句子。解释器模式提供了评估语言的语法或表达式的方式。 Interpreter is a behav…...

python读入和读出图像

python提供了PIL库和opencv库对图像进行读取并保存。 图像读入读出 给定一张RGB的彩色图像&#xff0c;PIL库将其读入: import cv2 from PIL import Image # 读入图像 image2 Image.open(cub1.jpg) print(type(image2)) image2_array np.array(image2) print(image2_array…...

每日一题——最长公共前缀

题目 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a;0≤n≤5000&#xff0c; 0≤len(strsi)≤5000 进阶&#xff1a;空间复杂度 O(1)&#xff0c;…...

iOS开发-WebRTC本地直播高分辨率不显示画面问题

iOS开发-WebRTC本地直播高分辨率不显示画面问题 在之前使用WebRTC结合ossrs进行推流时候&#xff0c;ossrs的播放端无法看到高分辨率画面问题。根据这个问题&#xff0c;找到了解决方案。 一、WebRTC是什么 WebRTC是什么呢&#xff1f; WebRTC (Web Real-Time Communicatio…...

python项目virtualenv环境部署正式项目和后台运行实践

pycharm创建virtualenv环境的项目&#xff1a; 在本地虚拟环境项目路径下生成依赖包记录文件&#xff0c;然后上传到linux 服务器项目路径下&#xff1a; 注意注意&#xff1a;要在虚拟环境中生成&#xff0c;才能将所有的项目依赖包构建在 requirements.txt文件中。 pip3 fre…...

平替 Docker - 玩转容器新利器 Podman Desktop (视频)

《OpenShift 4.x HOL教程汇总》 在 podman-desktop 1.2.1 podman 4.4 环境中验证。 文章目录 什么是 podman 和 podman-desktop安装 podman 和 podman-desktop 基本环境Image、Container 和 Pod 的基本操作拉取 Image运行 Container 将 Pod 部署到 Kubernetes安装 Kind 扩展插…...

nodejs+vue+elementui招聘求职网站系统的设计与实现-173lo

&#xff08;1&#xff09;管理员的功能是最高的&#xff0c;可以对系统所在功能进行查看&#xff0c;修改和删除&#xff0c;包括企业和用户功能。管理员用例如下&#xff1a; 图3-1管理员用例图 &#xff08;2&#xff09;企业关键功能包含个人中心、岗位类型管理、招聘信息…...

静态链接(7/13)

在一个软件项目中&#xff0c;为了完成特定功能&#xff0c;除了自定义函数&#xff0c;还可以使用别人已经封装好的函数库&#xff0c;如 C 函数库。库函数的使用避免了重复“造笼子”的重复工作&#xff0c;提高了代码复用率&#xff0c;大大减轻了软件开发的工作量。 库分为…...

jvs-rules API数据源配置说明(含配置APIdemo视频)

在JVS中&#xff0c;多数据源支持多种形态的数据接入&#xff0c;其中API是企业生产过程中常见的数据形态。使用数据源的集成配置&#xff0c;以统一的方式管理和集成多个API的数据。这些平台通常提供各种数据转换和处理功能&#xff0c;使得从不同数据源获取和处理数据变得更加…...

爬虫来介绍ChromeF12 谷歌开发者工具 -Network

了解网页基础(HTML、CSS、JavaScript) 了解HTTP基本原理 了解JSON格式 了解Ajax请求 了解爬虫基本原理 (一)、Chrome开发者工具面板概述 Elements 查找网页源代码HTML中的任一元素,手动修改任一元素的属性和样式且能实时在浏览器里面得到反馈。 比如我们在Event Listener…...

[足式机器人]Part4 机械设计 Ch00/01 绪论+机器结构组成与连接 ——【课程笔记】

本文仅供学习使用 本文参考&#xff1a; 《机械设计》 王德伦 马雅丽课件与日常作业可登录网址 http://edu.bell-lab.com/manage/#/login&#xff0c;选择观摩登录&#xff0c;查看2023机械设计2。 机械设计-Ch00Ch01——绪论机器结构组成与连接 Ch00-绪论0.1 何为机械设计——…...

Android isLoggable定制属于自己的log

Android原生自带的 android.util.Log&#xff0c;其中有一个 isLoggable 方法的运用 /** * Checks to see whether or not a log for the specified tag is loggable at the specified level.** The default level of any tag is set to INFO. This means that any level abov…...

【Spring Boot】构建RESTful服务 — 使用Swagger生成Web API文档

使用Swagger生成Web API文档 高质量的API文档在系统开发的过程中非常重要。本节介绍什么是Swagger&#xff0c;如何在Spring Boot项目中集成Swagger构建RESTful API文档&#xff0c;以及为Swagger配置Token等通用参数。 1.什么是Swagger Swagger是一个规范和完整的框架&…...

【实战】 九、深入React 状态管理与Redux机制(五) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...

PHP傻瓜也能搭建自己框架

PHP最简单自定义自己的框架&#xff08;一&#xff09; PHP最简单自定义自己的框架创建目录结构&#xff08;二&#xff09; PHP最简单自定义自己的框架定义常量自动生成目录&#xff08;三&#xff09; PHP最简单自定义自己的框架控制器自动加载运行&#xff08;四&#xf…...

为什么商业基础软件需要开源

Bytebase 本身是一家商业软件公司&#xff0c;而作为最核心资产的代码从 Day 0 却是开源的。同时我们还是 star-history.com 的运营者&#xff0c;大家在各种开源渠道会看到它生成的图&#xff1a; 一直以来&#xff0c;常会被别人问起的一个问题&#xff0c;就是为什么 Byteba…...

【自用】云服务器 使用 docker 搭建 HomeAssistant + MQTT 物联网平台

总览 1.搭建流程概述 2.准备工作 3.开始搭建&#xff01; 4.总结 如果想看 ESP32 或其他使用 MicroPython 编程的单片机如何连接到该云服务器&#xff0c;实现 HomeAssistant 控制 单片机的内容&#xff0c;请看我这篇博客的下一篇。 一、搭建流程概述 0.总体流程 我们需要…...

ABAP: SQL 多值查询

基础查数据 问题举例&#xff1a;例如查物料类型为ZFRT、ZROH和ZRSA的物料编码。 1、直接查询&#xff0c;三种不同类型的物料类型是或的关系。 SELECT DISTINCT ma~matnr ma~mtartFROM mara AS maINNER JOIN mbewh AS mbON ma~matnr mb~matnrINTO CORRESPONDING FIELDS OF…...

分布式学习最佳实践:从分布式系统的特征开始

正文   在延伸feature&#xff08;分布式系统需要考虑的特性&#xff09;的时候&#xff0c;我逐渐明白&#xff0c;这是因为要满足这些feature&#xff0c;才设计了很多协议与算法&#xff0c;也提出了一些理论。比如说&#xff0c;这是因为要解决去中心化副本的一致性问题&…...

第三章 图论 No.8最近公共祖先lca, tarjan与次小生成树

文章目录 lcaTarjan板子题&#xff1a;1172. 祖孙询问lca或tarjan&#xff1a;1171. 距离356. 次小生成树352. 闇の連鎖 lca O ( m l o g n ) O(mlogn) O(mlogn)&#xff0c;n为节点数量&#xff0c;m为询问次数&#xff0c;lca是一种在线处理询问的算法 自己也是自己的祖先 倍…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...