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

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函数构建表达式对象,并计算结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/41114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

扩散模型实战(四):从零构建扩散模型

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 本文以MNIST数据集为例&#xff0c;从…

智能楼宇综合布线实训室建设方案

一、楼宇智能综合布线实训室方案概述 楼宇智能综合布线实训室方案旨在为学生提供一个真实的学习和实践环境&#xff0c;以培养他们在楼宇智能综合布线领域的实际操作能力和技能。以下是一个概述&#xff1a; 1. 培养目标&#xff1a;培养学生在楼宇智能综合布线方面的综合能力…

Shader学习(三)(片元着色器)

1、在片元着色器处理漫反射 // Upgrade NOTE: replaced _World2Object with unity_WorldToObjectShader "Custom/specularfragement" {properties{_sp("Specular",color) (1,1,1,1)_shiness("Shiness",range(1,64)) 8}SubShader{pass {tags{&…

深入理解设计模式-行为型之模板(和回调区别联系)

概述 模板设计模式&#xff08;Template Design Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将算法的一些步骤延迟到子类中实现。模板设计模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板设计模式的核心思想…

网络通信原理应用层(第五十一课)

1)DNS:域名解析系统,端口号TCP或UDP的53 2)域名注册网站 -新网 www.xinnet.com -万网-阿里云 www.net.cn -中国互联 hulian.top 配置通过域名访问网站(NETBASE第七课)_IHOPEDREAM的博客-CSDN博客 2、FTP 1)FTP概述 -文件传输协议 -控制连接:TCP 21 <

对redis、redisson、springcache总结

<一> redis-缓存中间件 什么是redis redis是c语言开发的&#xff0c;一个高性能key-value键值对内存数据库&#xff0c;可以用来做数据库、缓存、消息中间件的一种非关系型数据库。 redis数据存储在哪里 内存和磁盘中&#xff0c;但是redis的读写都在内存中&#xff0c;…

leetcode-413. 等差数列划分(java)

等差数列划分 leetcode-413. 等差数列划分题目描述双指针 上期经典算法 leetcode-413. 等差数列划分 难度 - 中等 原题链接 - 等差数列划分 题目描述 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0…

16 脑洞大开:GUI测试还能这么玩

页面对象自动生成技术 页面对象自动生成技术&#xff0c;属于典型的“自动化你的自动化”的应用场景。它的基本思路是&#xff0c;你不用再手工维护 Page Class 了&#xff0c;只需要提供 Web 的 URL&#xff0c;它就会自动帮你生成这个页面上所有控件的定位信息&#xff0c;并…

JMeter接口测试数据分离驱动应用

步骤&#xff1a; 创建csv文件&#xff0c;编写接口测试用例 新建线程组——创建循环控制器&#xff08;循环次数填用例总数&#xff09; 创建CSV数据文件设置&#xff0c;设置参数。&#xff08;注意&#xff1a;是否允许带引号&#xff1f;&#xff1a;一定要设置为true&a…

深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想

大家好,我是微学AI,今天给大家介绍一下深度学习实战48-【未来的专家团队】基于AutoCompany模型的自动化企业概念设计与设想,文本将介绍AutoCompany模型的概念设计,涵盖了AI智能公司的各个角色,并结合了GPT-4接口来实现各个角色的功能,设置中央控制器,公司运作过程会生成…

【MFC常用问题记录】

MFC 记录 MFC的edit control控件显示1.控件添加变量M_edit后&#xff1a;2.控件ID为IDC_EDIT1: 线程函数使用 MFC的edit control控件显示 1.控件添加变量M_edit后&#xff1a; CString str; int x 10; str.Format(_T("%d"),x); M_edit.SetWindowText(str)2.控件ID…

JMM内存模型之happens-before阐述

文章目录 一、happens-before的定义二、happens-before的规则1. 程序顺序规则&#xff1a;2. 监视器锁规则&#xff1a;3. volatile变量规则&#xff1a;4. 传递性&#xff1a;5. start()规则&#xff1a;6. join()规则&#xff1a; 一、happens-before的定义 如果一个操作hap…

【编程二三事】ES究竟是个啥?

在最近的项目中&#xff0c;总是或多或少接触到了搜索的能力。而在这些项目之中&#xff0c;或多或少都离不开一个中间件 - ElasticSearch。 今天忙里偷闲&#xff0c;就来好好了解下这个中间件是用来干什么的。 ES是什么? ​ ES全称ElasticSearch&#xff0c;是个基于Lucen…

性能优化的重要性

性能优化的重要性 性能优化的重要性摘要引言注意事项代码示例及注释性能优化的重要性 性能优化的重要性在 Java 中的体现响应速度资源利用效率扩展性与可维护性并发性能合理的锁策略线程安全的数据结构并发工具类的应用避免竞态条件和死锁 总结代码示例 博主 默语带您 Go to Ne…

一张图看懂 USDT三种类型地址 Omni、ERC20、TRC20的区别

USDT是当前实用最广泛&#xff0c;市值最高的稳定币&#xff0c;它是中心化的公司Tether发行的。在今年的4月17日之前&#xff0c;市场上存在着2种不同类型的USDT。4月17日又多了一种波场TRC20协议发行的USDT&#xff0c;它们各自有什么区别呢?哪个转账最快到账&#xff1f;哪…

谷歌推出首款量子弹性 FIDO2 安全密钥

谷歌在本周二宣布推出首个量子弹性 FIDO2 安全密钥&#xff0c;作为其 OpenSK 安全密钥计划的一部分。 Elie Bursztein和Fabian Kaczmarczyck表示&#xff1a;这一开源硬件优化的实现采用了一种新颖的ECC/Dilithium混合签名模式&#xff0c;它结合了ECC抵御标准攻击的安全性和…

[LeetCode]矩阵对角线元素的和

解题 思路 1: 循环,找到主对角线的下标和副对角线的下标,如果矩阵长或宽为奇数的时候,需要减去中间公共的那一个值,中间公共的那个数的下标为mat[mat.size()/2][mat.size()/2]副对角线的下标为 mat [i][mat.size()-i-1] class Solution { public:int diagonalSum(vector<ve…

JVM中判定对象是否回收的的方法

引用计数法 引用计数法是一种垃圾回收&#xff08;Garbage Collection&#xff09;算法&#xff0c;用于自动管理内存中的对象。在引用计数法中&#xff0c;每个对象都有一个关联的引用计数器&#xff0c;用于记录对该对象的引用数量。 当一个新的引用指向对象时&#xff0c;…

Hive底层数据存储格式

前言 在大数据领域,Hive是一种常用的数据仓库工具,用于管理和处理大规模数据集。Hive底层支持多种数据存储格式,这些格式对于数据存储、查询性能和压缩效率等方面有不同的优缺点。本文将介绍Hive底层的三种主要数据存储格式:文本文件格式、Parquet格式和ORC格式。 一、三…

SpringBoot复习:(42)WebServerCustomizer的customize方法是在哪里被调用的?

ServletWebServletAutoConfiguration类定义如下&#xff1a; 可以看到其中通过Import注解导入了其内部类BeanPostProcessorRegister。 BeanPostProcessor中定义的registerBeanDefinition方法会被Spring容器调用。 registerBeanDefinitions方法调用了RegistrySyntheticBeanIf…