程序员必知!解释器模式的实战应用与案例分析

Java设计模式 - 程序员古德

解释器模式是一种灵活处理复杂语言或表达式的设计模式,以智能家居系统为例,用户可用自定义语言编写控制脚本,如“室温高则开空调”,先定义这种语言的简单文法,再构建解释器将脚本转为系统可理解的指令,这样,用户无需了解底层细节,就能轻松控制家居设备,未来添加新功能时,只需扩展文法和解释器,不影响现有脚本。

定义

程序员必知!解释器模式的实战应用与案例分析 - 程序员古德

解释器模式是一种行为设计模式,它提供了一种在运行时解析和执行特定语言的方式,在解释器模式中,通常定义一个语言的文法,然后实现一个解释器来解释这个文法,这种模式主要应用在需要处理一些复杂语言或者表达式,并且希望将这些语言或表达式转换成一些中间表示形式进行处理的场景中。

举一个业务中的实际案例:假设正在开发一个智能家居系统,用户可以通过系统提供的自定义语言来编写控制家居设备的脚本,比如“如果室内温度高于25度,则打开空调”,在这个场景中,可以使用解释器模式来设计系统,如下:

  1. 定义文法:需要定义一种简单的语言文法,用来描述用户的控制需求,比如包含条件语句、执行语句等。
  2. 构建解释器:根据定义的文法构建解释器,解释器能够解析用户编写的脚本,并将其转换成系统可以理解的中间表示形式。
  3. 执行操作:系统根据解释器解析的结果执行相应的操作,比如打开空调。

通过这种方式,可以让用户通过简单的脚本语言来控制复杂的家居设备,而不需要用户了解底层的实现细节,同时,如果以后需要添加新的控制功能,只需要扩展文法和解释器,而不需要修改用户已经编写好的脚本。

代码案例

程序员必知!解释器模式的实战应用与案例分析 - 程序员古德

反例

下面是一个未使用解释器模式的反例代码,在这个例子中,尝试实现一个简单的数学表达式求值功能。Calculator类,它包含了一个硬编码的求和方法,如下代码:

public class Calculator {  
    // 硬编码的求和方法,只能处理特定的表达式  
    public int calculate(int a, int b) {  
        // 假设这里总是执行加法操作  
        return a + b;  
    }  
}

创建client调用代码:

public class Client {  
    public static void main(String[] args) {  
        // 创建计算器实例  
        Calculator calculator = new Calculator();  
          
        // 调用求和方法,并输出结果  
        int result = calculator.calculate(3, 4);  
        System.out.println("Result of 3 + 4 is: " + result);  
    }  
}

执行上面的client代码,会得到以下输出:

Result of 3 + 4 is: 7

但这个代码存在一个问题,如果想要执行不同的数学操作(比如减法、乘法、除法等),Calculator类就无法满足需求了,因为它只支持加法操作,并且这个操作是硬编码在calculate方法中的,这就是未使用解释器模式的局限性:缺乏灵活性和可扩展性

正例

下面是一个使用解释器模式的正例代码,在这个代码中实现一个简单的数学表达式求值器,它能够解析并计算包含加法、减法和乘法的表达式。先定义一个Expression接口,它是所有表达式类的抽象基类:

// 表达式接口  
public interface Expression {  
    int interpret(Context context);  
}

创建实现了Expression接口的具体表达式类,这些类将代表加法、减法和乘法操作:

// 加法表达式类  
public class AddExpression implements Expression {  
    private Expression leftOperand;  
    private Expression rightOperand;  
  
    public AddExpression(Expression leftOperand, Expression rightOperand) {  
        this.leftOperand = leftOperand;  
        this.rightOperand = rightOperand;  
    }  
  
    @Override  
    public int interpret(Context context) {  
        return leftOperand.interpret(context) + rightOperand.interpret(context);  
    }  
}  
  
// 减法表达式类  
public class SubtractExpression implements Expression {  
    private Expression leftOperand;  
    private Expression rightOperand;  
  
    public SubtractExpression(Expression leftOperand, Expression rightOperand) {  
        this.leftOperand = leftOperand;  
        this.rightOperand = rightOperand;  
    }  
  
    @Override  
    public int interpret(Context context) {  
        return leftOperand.interpret(context) - rightOperand.interpret(context);  
    }  
}  
  
// 乘法表达式类  
public class MultiplyExpression implements Expression {  
    private Expression leftOperand;  
    private Expression rightOperand;  
  
    public MultiplyExpression(Expression leftOperand, Expression rightOperand) {  
        this.leftOperand = leftOperand;  
        this.rightOperand = rightOperand;  
    }  
  
    @Override  
    public int interpret(Context context) {  
        return leftOperand.interpret(context) * rightOperand.interpret(context);  
    }  
}

定义一个Context类,它用于存储变量值,在这个简单的例子中,不需要真正的上下文,但为了符合解释器模式的结构,还是创建一个,如下代码;

// 上下文类,用于存储变量值(在这个简单例子中,实际上并未使用)  
public class Context {  
    // 可以在这里添加存储变量值的逻辑  
}

创建client代码来构建表达式并调用解释器,如下代码:

public class Client {  
    public static void main(String[] args) {  
        // 创建上下文  
        Context context = new Context();  
  
        // 创建表达式树  
        // 例如表达式:(5 + 3) * 2  
        Expression five = new TerminalExpression(5);  
        Expression three = new TerminalExpression(3);  
        Expression addExpression = new AddExpression(five, three);  
        Expression two = new TerminalExpression(2);  
        Expression multiplyExpression = new MultiplyExpression(addExpression, two);  
  
        // 解释(计算)表达式  
        int result = multiplyExpression.interpret(context);  
  
        // 输出结果  
        System.out.println("Result of (5 + 3) * 2 is: " + result);  
    }  
}  
  
// 终端表达式类,代表数字字面量  
class TerminalExpression implements Expression {  
    private int value;  
  
    public TerminalExpression(int value) {  
        this.value = value;  
    }  
  
    @Override  
    public int interpret(Context context) {  
        return value;  
    }  
}

运行上面的client代码,会得到以下输出,如下:

Result of (5 + 3) * 2 is: 16

在这个例子中,使用了解释器模式来动态地构建和计算数学表达式,通过组合不同的表达式类(AddExpression, SubtractExpression, MultiplyExpression)可以创建复杂的表达式,并且解释器能够正确地计算其结果,TerminalExpression类代表了表达式中的终端符号,即数字字面量,这种模式使得表达式的解析和计算变得非常灵活和可扩展。

核心总结

程序员必知!解释器模式的实战应用与案例分析 - 程序员古德

解释器模式在日常Java开发过程中使用的非常多,它最大的优点在于灵活性:能动态地解释和执行代码,这在处理复杂逻辑或多变需求时特别有用,如编程语言解释器或动态配置系统,此外,解释器模式还支持可扩展性。它的缺点也很明显点,因为动态解释通常比预编译代码执行得更慢,同时,实现解释器模式可能相对复杂,需要仔细设计文法和解释逻辑。

在使用解释器模式时,要首先考虑性能要求,如果性能不是关键,且需要高度灵活性和可扩展性,解释器模式是很好的选择。反之,如果性能至关重要,或者需求相对固定,那么可能需要考虑其他模式。

关注我,每天学习互联网编程技术 - 程序员古德

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

固态继电器SSR光耦OR-806A ,对标替代AQW212

固态继电器 VL60V输出端击穿电压光耦 高隔离电压 60 至 600V 输出耐受电压 工业温度范围:-40 to 85℃ 高灵敏度和高速响应 特征 输入和输出之间的高隔离电压 (Viso:5000 V rms)。 控制低电平模拟信号 高灵敏度和高速响应 …

怎么提高客服满意度?

相应速度 1.即使平时回复手速很快,但一旦接待量一上来脑子转不过来,或是顾客咨询了一些自己不知道的问题,就知道快捷语有多重要。 2.熟悉快捷短语。(针对顾客提出的问题能快速给出反应。) 3. 安装快捷回复软件。(使用[客服宝]快捷回复软件…

使用代理IP池实现多线程爬虫的方法

目录 前言 代理IP的概念和作用 为什么使用代理IP池 代理IP池的实现步骤 代码实现 注意事项 总结 前言 随着互联网的发展,爬虫技术在各个领域中被广泛应用。然而,目标网站对爬虫的限制也日益严格,例如限制单个IP的请求频率。为了解决这…

达摩研究院Paraformer-large模型已支持windows

简介 FunASR是一个基础语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD)、标点恢复、语言模型、说话人验证、说话人分离和多人对话语音识别等。FunASR提供了便捷的脚本和教程&#xff0…

如何使用人工智能优化 DevOps?

DevOps 和人工智能密不可分,影响着各种业务。DevOps 可以加快产品开发速度并简化现有部署的维护,而 AI 则可以改变整个系统的功能。DevOps团队可以依靠人工智能和机器学习来进行数据集成、测试、评估和发布系统。更重要的是,人工智能和机器学…

【软件测试】学习笔记-设计GUI自动化测试策略

这篇文章从“实战”这个角度展开,探讨实际的大型全球化电商网站的GUI自动化测试如何开展。这场实战,从以下两个方面展开: 测试策略如何设计?这一点,我会根据亲身经历的实际项目,和你探讨GUI测试的分层测试…

使用rembg库提取图像前景(移除图像背景),并构建web应用

1、图像中的前景与背景 在深度学习图像处理领域中,图像内容可以被定义为前景与背景两部分,其中感兴趣图形的被定义为前景,不感兴趣区域的背景。如在目标检测中,被框出来的目标则被定义为前景。此外,前景识别也可以理解…

openssl快速生成自签名证书

系统:Centos 7.6 确保已安装openssl openssl version生成私钥文件 private.key (文件名自定义) openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048-out private.key:生成的私钥文件-algorithm RS…

从零学Java Set集合

Java Set集合 文章目录 Java Set集合1 Set 集合2 Set实现类2.1 HashSet【重点】2.2 LinkedHashSet2.3 TreeSet 3 Comparator 自定义比较器 1 Set 集合 特点:无序无下标、元素不可重复。 方法:全部继承自Collection中的方法。 常用方法: publ…

❤ Vue3 完整项目太白搭建 Vue3+Pinia+Vant3/ElementPlus+typerscript(一)yarn 版本控制 ltb (太白)

❤ 项目搭建 一、项目信息 Vue3 完整项目搭建 Vue3PiniaVant3/ElementPlustyperscript&#xff08;一&#xff09;yarn 版本控制 项目地址&#xff1a; 二、项目搭建 &#xff08;1&#xff09;创建项目 yarn create vite <ProjectName> --template vueyarn install …

最佳实践:如何在 SoapUI 中进行 REST 服务的测试

SoapUI 频繁地被选择为 SOAP 和 REST API 的自动化测试利器&#xff0c;得益于其友好的用户界面&#xff0c;测试人员毫不费力便可校验 REST 和 SOAP 协议的 Web 服务。它尤其适用于那些需要进行复杂测试的场合。 1、设置接口 我利用了 Swagger 去设置了一批即将投入使用的接…

zookeeper下载安装部署

zookeeper是一个为分布式应用提供一致性服务的软件&#xff0c;它是开源的Hadoop项目的一个子项目&#xff0c;并根据google发表的一篇论文来实现的。zookeeper为分布式系统提供了高效且易于使用的协同服务&#xff0c;它可以为分布式应用提供相当多的服务&#xff0c;诸如统一…

青年人格测验

青年人格量表也叫加州人格量表&#xff08;cpi&#xff09;&#xff0c;源于美国心理学家高夫的人格理论&#xff0c;共包含有18个维度&#xff0c;其中每个维度都是人格的基础元素&#xff0c;是人们在成长和外界交往中所形成的。 主要应用在人才测评领域&#xff0c;用来评估…

基于视频智能分析技术的AI烟火检测算法解决方案

一、背景需求 根据国家消防救援局公布的数据显示&#xff0c;2023年共接报处置各类警情213.8万起&#xff0c;督促整改风险隐患397万处。火灾危害巨大&#xff0c;必须引起重视。传统靠人工报警的方法存在人员管理难、场地数量多且分散等问题&#xff0c;无法有效发现险情降低…

Java并发之同步三:Condition条件队列

一、总览 二、源码分析 2.1 人口 public Condition newCondition() {return sync.newCondition();}final ConditionObject newCondition() {return new ConditionObject();}public class ConditionObject implements Condition, java.io.Serializable {private static final lo…

细说DMD芯片信号-DLP3

1&#xff0c; Block diagram 2. 信号介绍 2.1, LS interface&#xff1a; LD_Data_P/N(i), LD_CLK_P/N(i), LS_RDATA_A_BIST(O) 2.2, 视频信号: HSSI(High speed serial interface) High speed Differential Data pair lan A0~7 P/N, High speed Differential Clock A High…

《Vue2 进阶知识》动态挂载组件之Vue.extend + vm.$mount

前言 目前工作还是以 Vue2 为主&#xff0c;今早有人提问 如何动态挂载组件&#xff1f; 话说很久很久以前就实现过&#xff0c;今天再详细的整理一下此问题&#xff01; 开始 动态组件如下&#xff0c;是个简单的例子&#xff1a; 但请注意这里给了个 id"test2"…

CloudCompare——点云空间圆拟合

目录 1.概述2.软件实现3.完整操作4.算法源码5.相关代码 本文由CSDN点云侠原创&#xff0c;CloudCompare——点云空间圆拟合&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫与GPT生成的文章。 1.概述 CloudCompare软件中的To…

【Java反射】Java利用反射获取和设置对象某属性的值

通用工具类&#xff1a; package com.zlp.util;import com.fasterxml.jackson.annotation.JsonProperty;import java.lang.reflect.Field;public class ReflectUtil {/*** 反射获取对象的属性值** param object 对象&#xff08;要遍历的对象&#xff09;* param targetFieldN…

QT上位机开发(日志调试)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 程序开发中有很多的调试方法&#xff0c;比如说IDE调试&#xff0c;也就是设置断点、查看变量等等&#xff1b;比如说日志调试&#xff1b;比如说c…