18、设计模式之解释器模式(Interpreter)

news2025/1/16 20:12:46

一、什么是解释器模式
解释器模式是一种行为型设计模式。解释器模式就像是一种自定义语言,我们可以定义该语言的语法规则,然后从中解析出具体的命令或表达式,最终执行相应的操作。

eg:这种模式比较冷门,不怎么使用。

二、角色组成
抽象表达式(Abstract Expression):定义了解释器需要实现的接口。
终止符表达式(Terminal Expression):表示该语言中的终止符(例如,变量、函数等),终止符表达式的解释方法通常很简单,往往只包含一两行代码。
非终止符表达式(Nonterminal Expression):表示该语言中的非终止符(例如,语句块、条件语句、循环语句等),非终止符表达式的解释方法通常需要对内部表达式进行递归调用。
上下文(Context):存储了当前语言解释器的状态信息。
三、优缺点
优点:

扩展性好。由于解释器模式定义了语言的文法,因此可以很容易地添加新的表达式类和解释方法,从而扩展语言的解释能力。
灵活性高。由于解释器模式是基于接口设计的,因此可以很容易地替换解释器的实现或更改其执行方式,从而满足不同的需求。
缺点:

由于解释器模式需要定义很多类和解释方法,因此代码量比较大,实现起来有一定的复杂。度。
对于复杂的表达式,解释器模式的解释器可能需要占用更多的内存空间和运行资源,从而导致程序性能下降。
如果语言的文法非常复杂,解释器模式的实现可能会很困难,而且难以维护和扩展。
四、应用场景
4.1 生活场景
数学表达式求值:我们可以设计一个数学表达式解释器,将数学表达式解释为可计算的结果,从而方便进行运算。
游戏AI:通过解释器来解析AI所需的数据和指令,然后根据这些数据和指令执行相应的行为。
语言翻译:将一种语言的文本解析为另一种语言的文本。翻译器可以将输入的文本解析为一系列的单词、短语和句子,然后通过对这些语言结构进行翻译,将其转换成目标语言的文本。
4.2 java场景
正则表达式。正则表达式是一种用于描述字符串模式的语言,它可以非常灵活地描述满足特定模式的字符串,因此解释器模式是实现正则表达式的常用方法之一。
SQL解析器。SQL是一种结构化查询语言,用于在关系型数据库中进行数据操作和管理。为了将SQL语句转换为数据库操作,我们需要实现一个SQL解析器,将SQL语句解释为可执行的SQL命令,这就需要使用解释器模式。
java代码:需要编译器进行编译后才能运行,这个编译器就相当于解释器。
五、代码实现
下面以四则运算表达式,来解释一下解释器模式。

抽象表达式:Expression
终止符表达式:Constant、Variable
非终止符表达式:AddExpression、SubExpression
上下文:InterpreterVariables
5.0 UML类图

在这里插入图片描述

5.1 Expression——抽象表达式(Abstract Expression/**
 *
 * 1.抽象表达式(Abstract Expression)
 * 抽象表达式定义了用于解释特定语言的接口。
 */
public abstract class Expression {
    //定义解释器方法
    public abstract int interpret();
}
5.2 终结符表达式(Terminal Expression/**
 * 
 * 2.终结符表达式(Terminal Expression):变量
 * 终结符表达式表示语言中的终止符(例如,变量、关键字等)。
 */
public class Variable extends Expression{
    private String name;
 
    public Variable(String name) {
        this.name = name;
    }
 
    @Override
    public int interpret() {
        // 从上下文中获取该变量对应的值
        return InterpreterVariables.getValue(this.name);
    }
}
/**
 * 
 * 2.终结符表达式(Terminal Expression):常量
 * 终结符表达式表示语言中的终止符(例如,变量、关键字等)。
 */
public class Constant extends Expression{
    private int value;
 
    public Constant(int value) {
        this.value = value;
    }
 
    @Override
    public int interpret() {
        // 直接返回常量值
        return value;
    }
}
5.3 非终结符表达式(Nonterminal Expression/**
 * 
 * 3.非终结符表达式(Nonterminal Expression):加法运算
 * 非终结符表达式表示语言中的非终止符(例如,语句块、语句等)。
 */
public class AddExpression extends Expression{
    // 左操作数
    private Expression left;
    // 右操作数
    private Expression right;
 
    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
 
    @Override
    public int interpret() {
        // 对左右操作数分别进行解释器求值,然后计算结果
        return left.interpret() + right.interpret();
    }
}
/**
 * 
 * 3.非终结符表达式(Nonterminal Expression):减法运算
 * 非终结符表达式表示语言中的非终止符(例如,语句块、语句等)。
 */
public class SubExpression extends Expression{
    private Expression left;
    private Expression right;
 
    public SubExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
 
    @Override
    public int interpret() {
        return left.interpret() - right.interpret();
    }
}
5.4 InterpreterVariables——上下文(Context/**
 * 
 * 4.上下文(Context):负责存储变量名和其值之间的映射关系
 * 上下文保存了解释器解释表达式需要的信息。
 */
public class InterpreterVariables {
    private static Map<String, Integer> variables = new HashMap<>();
 
    // 根据变量名获取其对应的值
    public static int getValue(String name) {
        if(variables.containsKey(name)) {
            return variables.get(name);
        }
        // 默认返回0
        return 0;
    }
 
    // 设置变量名和其对应的值
    public static void setValue(String name, int value) {
        variables.put(name, value);
    }
}
5.5 testInterpreter
/**
 * 
 * 解释器模式测试类
 */
@SpringBootTest
public class TestInterpreter {
    @Test
    void testInterpreter(){
        // 创建变量x、y和常量1,并设置变量x和y的值
        Variable x = new Variable("x");
        Variable y = new Variable("y");
        Constant c = new Constant(1);
 
        InterpreterVariables.setValue("x", 10);
        InterpreterVariables.setValue("y", 5);
 
        // 创建解释器表达式(x - y)+ 1
        Expression expression = new AddExpression(new SubExpression(x, y), c);
 
        // 解释表达式,并获取最终结果
        int result = expression.interpret();
        System.out.println("计算结果:" + result);
    }
}

在这里插入图片描述
六、总结
解释器是一个简单的语法分析工具,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。因此,尽量不要在重要的模块中使用解释器模式,在项目中可以使用shell、JRuby、Groovy等脚本语言来代替解释器模式,也可以用开源包,比如Express4J、JEP,功能都很强大。
出现以下场景,可以考虑使用(尽量别用,大佬除外):

需要定义一种自定义语言,并对其进行解析和执行。
需要实现一种自定义的文件格式,并对其进行解析和处理。
需要对复杂的数据结构进行解析,并对其进行处理或转换。
需要实现一些自定义的算法或规则,并对其进行解析和执行。

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

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

相关文章

【安卓】Android开发入门 你的第一个apk应用

本文介绍如何写一个入门的安卓apk应用, 以嵌套一个网页为例。 开发ide&#xff1a;Android studio 语言&#xff1a;Kotlin tips: 最好别下载新版本的 Android studio &#xff0c;因为新版的界面有所改动 遇到问题去网上搜 新手刚入门可能界面都找不到在哪里&#xff1b;其次…

UI设计中的图标的分类,功能性图标

图标的分类 既然知道了图标的作用和重要性&#xff0c;那么接下来&#xff0c;就要进一步了解在工作中我们要设计哪些图标。图标可以划分成三种大类:功能性图标、装饰性图标、启动图标。 功能性图标 功能图标是具有指代意义且具有功能标识的图形&#xff0c;它不仅是一种图形&a…

vue.js 页面中设置多个swiper

效果&#xff1a; 设置主要设置了 动态的 包含类、 左右按钮的类 <template><div class"swiper-container_other"><!-- 右侧按钮 --><div :class"[(id)?swiper-button-nextid:swiper-button-next, swiper-button-next]"></div…

阿里云数据盘挂载目录

1、先登录服务器创建新目录aaa 2、云盘都快照备份下。后续操作完核实无误了&#xff0c;您根据您需求删除快照就行&#xff0c; 然后登录服务器内执行&#xff1a; fdisk -l lsblk blkid ll /aaa 3、执行&#xff1a;&#xff08;以下命令是进行数据盘做ext4文件系统并挂载到…

北京市办理大兴道路运输许可证所需条件及注意事项

尊敬的客户&#xff1a; 感谢您选择北京经典世纪集团有限公司作为您的信任合作伙伴。我们从多个角度&#xff0c;为您详细解析办理大兴道路运输许可证所需的条件及注意事项&#xff0c;以便您轻松高效地完成相关手续。&#xff08;游览器搜经典世纪胡云帅&#xff09;。 我们…

旧物置换网站|基于springboot+ Mysql+Java+B/S架构的旧物置换网站设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 注册登录界面 个人中心 用户功能模块 管理员功能登录前台功能效果图 卖家功能…

华为三层交换机:ACL的基本实验

实验要求&#xff1a; PC1不允许访问PC3&#xff0c;PC3可以访问PC1 分析问题&#xff1a; PC1不允许访问PC3&#xff0c;问题中含有“目标地址”则我们需要设置目标地址&#xff0c;这样基本ACL是不行的&#xff0c;必须使用高级ACL [sw1]acl ? INTEGER<2000-2999>…

Go语言中的锁与管道的运用

目录 1.前言 2.锁解决方案 3.管道解决方案 4.总结 1.前言 在写H5小游戏的时候&#xff0c;由于需要对多个WebSocket连接进行增、删、查的管理和对已经建立连接的WebSocket通过服务端进行游戏数据交换的需求。于是定义了一个全局的map集合进行连接的管理&#xff0c;让所有…

HarmonyOS NEXT应用开发之异常处理案例

介绍 本示例介绍了通过应用事件打点hiAppEvent获取上一次应用异常信息的方法&#xff0c;主要分为应用崩溃、应用卡死以及系统查杀三种。 效果图预览 使用说明&#xff1a; 点击构建应用崩溃事件&#xff0c;3s之后应用退出&#xff0c;然后打开应用进入应用异常页面&#x…

常青内容与病毒式内容——哪个更适合 SEO?

常青内容是经得起时间考验的内容&#xff0c;而病毒式内容则是利用特定时代潮流的内容。 如果你曾经考虑过为网站添加内容&#xff0c;你可能听说过常青内容和病毒式内容这两个词。这两个词涵盖了网站所需的基本内容类型。 那么&#xff0c;这两者之间有什么区别&#xff1f;…

2024年软考计划开始了,你准备好了吗?

目录标题 2024年度计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试工作计划计算机软考中级科目哪个含金量最高&#xff1f;报考流程和说明 2024年度计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试工作计划 一、2024年度计算机软件资格考试(初级…

4款好用的AI写作软件推荐,让你成为写作大神

写作已经成为我们日常生活和工作中必不可少的一部分&#xff0c;当我们在还绞尽脑汁的去想如何写作的时候&#xff0c;别人已经弯道超车用上了人工智能写作软件&#xff0c;今天&#xff0c;小编想为大家推荐4款好用的AI写作软件&#xff0c;让你在几秒钟内生成高质量文章的同时…

IDEA启动时,电脑非常的卡

选择Help -> Change memory Settings 把启动内存调大一点就行了&#xff0c;反正要超过你平时使用IDEA时使用到的内存大小就行。 原因解释&#xff1a; JVM在运行时会回收新生代和老年代的垃圾&#xff0c;新生代无法回收的对象&#xff0c;比如&#xff1a;回收15次都没有…

【一】【设计模式】类关系UML图

1. 继承&#xff08;Generalization&#xff09; 继承是对象间的一种层次关系&#xff0c;允许子类继承并扩展父类的功能。 UML线&#xff1a;带有空心箭头的直线&#xff0c;箭头指向基类&#xff08;父类&#xff09;。 class Parent {public void parentMethod() {System.…

Android Studio下运行java main 方法

方法一 修改项目的.idea中的gradle.xml文件&#xff0c;在GradleProjectSettings标签下添加一行代码 <option name"delegatedBuild" value"false" />方法二 main方法上右键选择Run ‘xxx’ with Coverage

提高螺栓连接强度——SunTorque智能扭矩系统

螺栓连接是工程中常见的一种连接方式&#xff0c;其强度对于设备的稳定性和安全性具有至关重要的影响。然而&#xff0c;由于各种因素的影响&#xff0c;螺栓连接在使用过程中往往会出现松动、断裂等问题&#xff0c;导致设备故障和安全隐患。因此&#xff0c;提高螺栓连接的强…

【大模型API调用初尝试一】智谱AI 通义千问

大模型API调用初尝试一 调用大模型API能干什么智谱AI大模型API调用的过程获取API_KEYGLM_4同步调用GLM_4异步调用文生图大模型API调用 阿里云通义千问API调用过程单轮会话多轮会话 调用大模型API能干什么 大模型的参数非常庞大&#xff0c;功能非常强大&#xff0c;但是训练成…

MySQL中ON DUPLICATE KEY UPDATE的介绍与使用、批量更新、存在即更新不存在则插入

文章目录 一、ON DUPLICATE KEY UPDATE的介绍二、ON DUPLICATE KEY UPDATE的使用2.1、案例一&#xff1a;根据主键id进行更新2.2、案例二&#xff1a;根据唯一索引进行更新&#xff08;常用&#xff09;2.3、案例三&#xff1a;没有主键或唯一键字段值相同就插入2.4、案例四&am…

C#、C++、Java、Python 选择哪个好?

作者&#xff1a;网博汇智 链接&#xff1a;https://www.zhihu.com/question/298323023/answer/2789627224 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 一个好的程序员不能把自己绑定在一种语言上&#xff0c;不…

element ui 中文离线文档(百度云盘下载)

一般内网开发上不了网&#xff0c;用离线版本比较方便&#xff0c;下载地址&#xff1a; https://download.csdn.net/download/li836779537/88355878?spm1001.2014.3001.5503 下载后里面有个 index.hrml 双击打开就可以用 效果如下&#xff1a;