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

设计模式之解释器模式详解及实例

1、解释器设计模式概述:

解释器模式(Interpreter Pattern)是一种设计模式,它主要用于描述如何构建一个解释器以解释特定的语言或表达式。该模式定义了一个文法表示和解释器的类结构,用于解释符合该文法规则的语句。解释器模式通常用于实现编程语言解释器、自定义脚本引擎等场景。

在解释器模式中,有以下几个关键角色:

  • 抽象表达式(Abstract Expression):定义一个接口,用于表示不同类型的表达式。

  • 终结符表达式(Terminal Expression):实现抽象表达式接口的具体类,用于解释终结符表达式。

  • 非终结符表达式(Non-Terminal Expression):实现抽象表达式接口的具体类,用于解释非终结符表达式。

  • 上下文(Context):包含解释器需要的全局信息以及待解释的表达式。

  • 客户端(Client):构建解释器并调用解释方法。

2、解释器设计模式的适用场景:

  • 当需要开发一个解释器,用于解释特定的语言或表达式时。

  • 当需要表示一个复杂的语法规则,并且希望易于扩展和维护时。

  • 当需要解释一些固定的文法,如数学表达式、逻辑表达式等场景。

3、解释器设计模式的优点:

  • 易于扩展:当需要增加新的文法规则时,只需增加新的非终结符表达式类,无需修改原有代码,符合开闭原则。

  • 解耦:将文法规则的表示和解释过程分离,使得代码结构更清晰。

  • 易于维护:每个文法规则对应一个非终结符表达式类,当需要修改或维护某个规则时,只需修改对应的类即可。

举例说明:假设我们需要实现一个简单的计算器,支持加法和减法运算。我们可以通过解释器模式构建表达式类,分别表示加法和减法运算,以便能够解析和计算输入的表达式。

4、解释器设计模式的缺点:

  • 执行效率较低:解释器模式通常需要递归调用,导致执行效率较低。

  • 难以应对复杂的文法规则:当文法规则非常复杂时,解释器模式的类结构可能变得非常复杂,难以维护。

5、用C++实现一个解释器设计模式例子:

#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>class Expression {
public:virtual ~Expression() = default;virtual int interpret() const = 0;
};class AddExpression : public Expression {
private:std::shared_ptr<Expression> leftExpression;std::shared_ptr<Expression> rightExpression;public:AddExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right): leftExpression(left), rightExpression(right) {}int interpret() const override {return leftExpression->interpret() + rightExpression->interpret();}
};class SubtractExpression : public Expression {
private:std::shared_ptr<Expression> leftExpression;std::shared_ptr<Expression> rightExpression;public:SubtractExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right): leftExpression(left), rightExpression(right) {}int interpret() const override {return leftExpression->interpret() - rightExpression->interpret();}
};class NumberExpression : public Expression {
private:int number;public:explicit NumberExpression(int number) : number(number) {}int interpret() const override {return number;}
};std::shared_ptr<Expression> parseExpression(const std::string& expression) {size_t pos = expression.find_first_of("+-");if (pos == std::string::npos) {throw std::invalid_argument("Invalid expression");}std::shared_ptr<Expression> left = std::make_shared<NumberExpression>(std::stoi(expression.substr(0, pos)));std::shared_ptr<Expression> right = std::make_shared<NumberExpression>(std::stoi(expression.substr(pos + 1)));if (expression[pos] == '+') {return std::make_shared<AddExpression>(left, right);} else {return std::make_shared<SubtractExpression>(left, right);}
}int main() {std::string input;std::cout << "Enter an expression (e.g., 3+2 or 7-4): ";std::cin >> input;try {auto expression = parseExpression(input);std::cout << "Result: " << expression->interpret() << std::endl;} catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;}return 0;
}

        在这个例子中,我们定义了一个Expression接口,它包含一个纯虚函数interpret,用于计算表达式的值。我们实现了三个具体的表达式类:AddExpression(用于表示加法表达式),SubtractExpression(用于表示减法表达式)和NumberExpression(用于表示数字)。

        parseExpression函数接受一个字符串参数,它解析输入的字符串并根据运算符构建对应的Expression对象。main函数从用户获取输入的表达式,调用parseExpression函数构建表达式对象,并计算结果。

相关文章:

设计模式之解释器模式详解及实例

1、解释器设计模式概述&#xff1a; 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种设计模式&#xff0c;它主要用于描述如何构建一个解释器以解释特定的语言或表达式。该模式定义了一个文法表示和解释器的类结构&#xff0c;用于解释符合该文法规则的语句。解…...

Nodejs沙箱逃逸--总结

一、沙箱逃逸概念 JavaScript和Nodejs之间有什么区别&#xff1a;JavaScript用在浏览器前端&#xff0c;后来将Chrome中的v8引擎单独拿出来为JavaScript单独开发了一个运行环境&#xff0c;因此JavaScript也可以作为一门后端语言&#xff0c;写在后端&#xff08;服务端&#…...

No115.精选前端面试题,享受每天的挑战和学习

文章目录 变量提升和函数提升的顺序Event Loop封装 FetchAPI&#xff0c;要求超时报错的同时&#xff0c;取消执行的 promise&#xff08;即不继续执行&#xff09;强缓存和协商缓存的区别token可以放在cookie里吗&#xff1f; 变量提升和函数提升的顺序 在JavaScript中&#…...

Elasticsearch:语义搜索 - Semantic Search in python

当 OpenAI 于 2022 年 11 月发布 ChatGPT 时&#xff0c;引发了人们对人工智能和机器学习的新一波兴趣。 尽管必要的技术创新已经出现了近十年&#xff0c;而且基本原理的历史甚至更早&#xff0c;但这种巨大的转变引发了各种发展的“寒武纪大爆炸”&#xff0c;特别是在大型语…...

Flink学习笔记(一)

流处理 批处理应用于有界数据流的处理&#xff0c;流处理则应用于无界数据流的处理。 有界数据流&#xff1a;输入数据有明确的开始和结束。 无界数据流&#xff1a;输入数据没有明确的开始和结束&#xff0c;或者说数据是无限的&#xff0c;数据通常会随着时间变化而更新。 在…...

[Raspberry Pi]如何用VNC遠端控制樹莓派(Ubuntu desktop 23.04)?

之前曾利用VMware探索CentOS&#xff0c;熟悉Linux操作系統的指令和配置運作方式&#xff0c;後來在樹莓派價格飛漲的時期&#xff0c;遇到貴人贈送Raspberry Pi 4 model B / 8GB&#xff0c;這下工具到位了&#xff0c;索性跳過樹莓派官方系統(Raspberry Pi OS)&#xff0c;直…...

17.HPA和rancher

文章目录 HPA部署 metrics-server部署HPA Rancher部署Rancherrancher添加集群仪表盘创建 namespace仪表盘创建 Deployments仪表盘创建 service 总结 HPA HPA&#xff08;Horizontal Pod Autoscaling&#xff09;Pod 水平自动伸缩&#xff0c;Kubernetes 有一个 HPA 的资源&…...

VS2022远程Linux使用cmake开发c++工程配置方法

文章目录 远程连接CMakePresets.json的配置Task.vs.json配置launch.vs.json配置最近使用别人在VS2015上使用visualgdb搭建的linux开发环境,各种不顺手,一会代码不能调转了,一会行号没了,调试的时候断不到正确的位置,取消的断点仍然会进。因此重新摸索了一套使用vs的远程开…...

《强化学习:原理与Python实战》——可曾听闻RLHF

前言&#xff1a; RLHF&#xff08;Reinforcement Learning with Human Feedback&#xff0c;人类反馈强化学习&#xff09;是一种基于强化学习的算法&#xff0c;通过结合人类专家的知识和经验来优化智能体的学习效果。它不仅考虑智能体的行为奖励&#xff0c;还融合了人类专家…...

STM32——RTC实时时钟

文章目录 Unix时间戳UTC/GMT 时间戳转换BKP简介BKP基本结构读写BKP备份寄存器电路设计关键代码 RTC简介RTC框图RTC基本结构硬件电路RTC操作注意事项读写实时时钟电路设计关键代码 Unix时间戳 Unix 时间戳&#xff08;Unix Timestamp&#xff09;定义为从UTC/GMT的1970年1月1日…...

webSocket 开发

1 认识webSocket WebSocket_ohana&#xff01;的博客-CSDN博客 一&#xff0c;什么是websocket WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽…...

c#设计模式-结构型模式 之 代理模式

前言 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时&#xff0c;访问对象不适合或者不能直接 引用目标对象&#xff0c;代理对象作为访问对象和目标对象之间的中介。在学习代理模式的时候&#xff0c;可以去了解一下Aop切面编程AOP切面编程_aop编程…...

openpnp - 自动换刀的设置

文章目录 openpnp - 自动换刀的设置概述笔记采用的openpnp版本自动换刀库的类型选择自动换刀设置前的注意事项先卸掉吸嘴座上所有的吸嘴删掉所有的吸嘴设置自动换刀的视觉识别设置吸嘴座为自动换刀 - 以N1为例备注补充 - 吸嘴轴差个0.3mm, 就有可能怼坏吸嘴END openpnp - 自动换…...

《HeadFirst设计模式(第二版)》第十章代码——状态模式

如下图所示&#xff0c;这是一个糖果机的状态机图&#xff0c;要求使用代码实现&#xff1a; 初始版本&#xff1a; package Chapter10_StatePattern.Origin;/*** Author 竹心* Date 2023/8/19**/public class GumballMachine {final static int SOLD_OUT 0;final static int…...

day-25 代码随想录算法训练营(19)回溯part02

216.组合总和||| 思路&#xff1a;和上题一样&#xff0c;差别在于多了总和&#xff0c;但是数字局限在1-9 17.电话号码的字母组合 思路&#xff1a;先纵向遍历第i位电话号码对于的字符串&#xff0c;再横向递归遍历下一位电话号码 93.复原IP地址 画图分析&#xff1a; 思…...

PG逻辑备份与恢复

文章目录 创建测试数据pg_dump 备份pg_restore 恢复pg_restore 恢复并行备份的文件PG 只导出指定函数 创建测试数据 drop database if exists test; create database test ; \c test create table t1(id int primary key); create table t2(id serial primary key, name varch…...

图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010

然后我们再来看一下这个明星关系图谱 可以看到这里 这个是原来的startRelation 我们可以写CQL去查询对应的关系 可以看到,首先查询出来以后,然后就可以去创建 我们可以把写的创建明星关系的CQL,拿到 springboot中去执行 可以看到,这里我们先写一个StarRelationRepository,然…...

Linux网络编程:Socket套接字编程(Server服务器 Client客户端)

文章目录&#xff1a; 一&#xff1a;定义和流程分析 1.定义 2.流程分析 3.网络字节序 二&#xff1a;相关函数 IP地址转换函数inet_pton inet_ntop&#xff08;本地字节序 网络字节序&#xff09; socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…...

Mac OS下应用Python+Selenium实现web自动化测试

在Mac环境下应用PythonSelenium实现web自动化测试 在这个过程中要注意两点&#xff1a; 1.在终端联网执行命令“sudo pip install –U selenium”如果失败了的话&#xff0c;可以尝试用命令“sudo easy_install selenium”来安装selenium; 2.安装好PyCharm后新建project&…...

每天一道leetcode:934. 最短的桥(图论中等广度优先遍历)

今日份题目&#xff1a; 给你一个大小为 n x n 的二元矩阵 grid &#xff0c;其中 1 表示陆地&#xff0c;0 表示水域。 岛 是由四面相连的 1 形成的一个最大组&#xff0c;即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。 你可以将任意数量的 0 变为 1 &#…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

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

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

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...