【HeadFirst系列之HeadFirst设计模式】第18天之深入解析解释器模式:从原理到实战

深入解析解释器模式:从原理到实战

在软件开发中,我们经常需要解析特定的语言或表达式,例如:

  • 数学表达式(计算 2 + 3 * 5)。
  • SQL 解析(解析 SELECT * FROM users WHERE age > 18)。
  • 正则表达式(匹配字符串模式)。
  • 自定义 DSL(领域特定语言)(如 Spring EL 表达式)。

这些场景都涉及 将文本转换为可执行逻辑,而这正是 解释器模式(Interpreter Pattern) 解决的问题。


📌 1. 什么是解释器模式?

解释器模式(Interpreter Pattern)是一种 行为型设计模式,用于定义一种语言的语法,并提供解释这些语法的解释器。

💡 一句话概括如果你的程序需要解析和执行某种语言(或类语言)表达式,解释器模式就是一个很好的选择!

📜 经典案例:数学表达式计算

  • 需求:解析并计算数学表达式 "2 + 3 * 5"
  • 方案:使用解释器模式,将表达式拆分为 终结符(数字)非终结符(操作符),然后逐层解析并计算结果。

📌 2. 解释器模式的核心概念

解释器模式通常包含以下组件:

  1. 抽象表达式(Expression):定义解释器的接口。
  2. 终结符表达式(TerminalExpression):表示表达式中的具体值(如数字)。
  3. 非终结符表达式(NonTerminalExpression):表示运算符(如加法、乘法)。
  4. 上下文(Context):存储解释器运行时的环境信息。
  5. 客户端(Client):构建语法树,并调用解释方法。

📌 3. 代码实战:数学表达式解析器

🎯 目标:解析和计算简单的数学表达式

示例表达式:2 + 3 * 5,按运算符优先级,结果应为 2 + (3 * 5) = 17

🖥️ 代码实现

import java.util.Map;

// 1️⃣ 抽象表达式(Expression)
interface Expression {
    int interpret(Map<String, Integer> context);
}

// 2️⃣ 终结符表达式(数字)
class NumberExpression implements Expression {
    private final int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return number;
    }
}

// 3️⃣ 非终结符表达式(加法)
class AddExpression implements Expression {
    private final Expression left, right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 4️⃣ 非终结符表达式(乘法)
class MultiplyExpression implements Expression {
    private final Expression left, right;

    public MultiplyExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return left.interpret(context) * right.interpret(context);
    }
}

// 5️⃣ 客户端代码
public class InterpreterPatternDemo {
    public static void main(String[] args) {
        // 表达式:2 + 3 * 5
        Expression num2 = new NumberExpression(2);
        Expression num3 = new NumberExpression(3);
        Expression num5 = new NumberExpression(5);

        Expression multiply = new MultiplyExpression(num3, num5); // 3 * 5
        Expression add = new AddExpression(num2, multiply);       // 2 + (3 * 5)

        // 计算并输出结果
        System.out.println("结果: " + add.interpret(Map.of())); // 结果: 17
    }
}

📢 代码解析

  • NumberExpression 负责解析数字。
  • AddExpression 负责解析 + 运算。
  • MultiplyExpression 负责解析 * 运算,并保证 乘法优先级高于加法
  • 构建 AST(抽象语法树) 来解析 2 + 3 * 5,计算结果 17

📌 4. 解释器模式的应用场景

✅ 适用场景

解释器模式适用于 语言解析、规则匹配、计算表达式 等场景:

  1. 数学计算(如计算器)
  2. SQL 解析(如 MyBatis 的 SQL 语法解析器)
  3. 正则表达式(如 Pattern.compile()
  4. 领域特定语言(DSL)(如 Spring EL 表达式)
  5. 脚本语言解析(如 Groovy、JS 解析器)

❌ 不适用场景

解释器模式适用于小规模解析任务,但对于复杂语言(如 Java、Python 解析器),其 效率较低,一般采用 编译器技术(如 ANTLR、Lex、YACC)


📌 5. 解释器模式在 JDK 和 Spring 中的应用

🚀 1. 在 JDK 中

Java 内部使用了解释器模式来解析 正则表达式

Pattern pattern = Pattern.compile("\\d+"); // 解析整数
Matcher matcher = pattern.matcher("12345");
System.out.println(matcher.matches()); // true

Pattern.compile() 就是一个 解释器,它将 正则表达式转换为可执行的匹配逻辑

🌱 2. 在 Spring 中

Spring 使用解释器模式解析 Spring EL(表达式语言)

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("10 * (2 + 3)");
Integer result = exp.getValue(Integer.class);
System.out.println(result); // 50

Spring EL 允许动态解析 数学运算、Bean 访问、方法调用,是 Spring AOP、Spring Security 规则解析的重要基础。


📌 6. 解释器模式的优缺点

✅ 优点

  1. 代码可扩展性强:新规则可通过扩展 Expression 轻松添加。
  2. 符合开闭原则:不同表达式逻辑封装在不同类中,修改影响较小。
  3. 可读性好:语法规则清晰,易于维护。

❌ 缺点

  1. 性能较低:对于复杂表达式,递归解析 AST 可能导致性能瓶颈
  2. 不适合大型语言解析:解析 Java / Python 代码通常使用 ANTLR 而非解释器模式。
  3. 类爆炸:复杂语法需要大量 Expression 相关类,增加维护成本。

📌 7. 总结

  • 解释器模式用于解析和执行特定语言(表达式),如数学计算、DSL、正则表达式。
  • 核心组件包括 Expression、终结符表达式、非终结符表达式、上下文等
  • 适用于小规模解析任务,复杂语言解析需借助编译器工具
  • 在 JDK(正则表达式)和 Spring(SpEL 解析)中广泛应用

💡 你是否在项目中遇到类似需求?欢迎留言讨论! 🚀

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

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

相关文章

【论文解读】MODEST 透明物体 单目深度估计和分割 ICRA 2025

MODEST是一种用于透明物体的单目深度估计和分割的方法&#xff0c;来自ICRA 2025。 它通过单张RGB图像作为输入&#xff0c;能够同时预测透明物体的深度图和分割掩码。 由深度图生成点云数据&#xff0c;然后采用GraspNet生成抓取位姿&#xff0c;开展透明物体抓取实验。 论文…

基于SpringBoot的美食信息推荐系统设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

Unity--Cubism Live2D模型使用

了解LIVE2D在unity的使用--前提记录 了解各个组件的作用 Live2D Manuals & Tutorials 这些文件都是重要的控制动画参数的 Cubism Editor是编辑Live2D的工具&#xff0c;而导出的数据的类型&#xff0c;需要满足以上的条件 SDK中包含的Cubism的Importer会自动生成一个Pref…

2025人工智能AI新突破:PINN内嵌物理神经网络火了

最近在淘金的时候发现基于物理信息的神经网络&#xff08;简称PINN&#xff09;也是个研究热点&#xff0c;遂研读了几篇经典论文&#xff0c;深觉这也是个好发论文的方向&#xff0c;所以火速整理了一些个人认为很值得一读的PINN论文和同学们分享。 为了方面同学们更好地理解…

大模型是如何工作的

近几十年来&#xff0c;人工智能经历了从基础算法到生成式AI的深刻演变。生成式AI通过学习大量数据可以创造出全新的内容&#xff0c;如文本、图像、音频和视频&#xff0c;这极大地推动了AI技术的广泛应用。常见的应用场景包括智能问答&#xff08;如通义千问、GPT&#xff09…

Qt常用控件之 纵向列表QListWidget

纵向列表QListWidget QListWidget 是一个纵向列表控件。 QListWidget属性 属性说明currentRow当前被选中的是第几行。count一共有多少行。sortingEnabled是否允许排序。isWrapping是否允许换行。itemAlignment元素的对齐方式。selectRectVisible被选中的元素矩形是否可见。s…

利用pdf.js+百度翻译实现PDF翻译,创建中文PDF

基于JavaScript的PDF文档解析与智能翻译系统开发实践 一、功能预览 1.1 PDF加载 1.2 PDF翻译 二、系统架构设计 2.1 PDF智能翻译系统架构设计 层级模块名称功能描述技术实现呈现层Canvas渲染器PDF文档可视化渲染PDF.js + 动态视口计算 + 矩阵变换

Java数据结构第十九期:解构排序算法的艺术与科学(一)

专栏&#xff1a;Java数据结构秘籍 个人主页&#xff1a;手握风云 目录 一、排序的概念及引用 1.1. 排序的概念 1.2. 排序的应用 1.3. 常见的排序算法 二、常见排序算法的实现 2.1. 直接插入排序 2.2. 希尔排序 一、排序的概念及引用 1.1. 排序的概念 所谓排序&#xf…

1.2TypeScript 类型系统在前端的革命性意义

文章目录 **一、前端开发的类型觉醒&#xff08;历史背景&#xff09;****二、类型系统的核心价值****三、类型系统与现代框架的化学反应****四、高级类型编程实战****五、工程化影响深度解析****六、生态系统的蝴蝶效应****七、企业级应用实践数据****八、类型系统的局限性***…

K8S学习之基础十九:k8s的四层代理Service

K8S四层代理Service 四层负载均衡Service 在k8s中&#xff0c;访问pod可以通过ip端口的方式&#xff0c;但是pod是由生命 周期的&#xff0c;pod在重启的时候ip地址往往会发生变化&#xff0c;访问pod就需要新的ip地址&#xff0c;这样就会很麻烦&#xff0c;每次pod地址改变就…

Varlens(手机上的单反)Ver.1.9.3 高级版.apk

Varlens 是一款专业级手机摄影软件&#xff0c;旨在通过丰富的功能和高自由度参数调节&#xff0c;让手机拍摄效果媲美微单相机。以下是核心功能总结&#xff1a; 一、核心功能 专业拍摄模式 支持手动/自动/程序模式&#xff0c;可调节ISO、快门速度、EV、白平衡等参数27 提供…

用Deepseek写一个 HTML 和 JavaScript 实现一个简单的飞机游戏

大家好&#xff01;今天我将分享如何使用 HTML 和 JavaScript 编写一个简单的飞机游戏。这个游戏的核心功能包括&#xff1a;控制飞机移动、发射子弹、敌机生成、碰撞检测和得分统计。代码简洁易懂&#xff0c;适合初学者学习和实践。 游戏功能概述 玩家控制&#xff1a;使用键…

物联网IoT系列之MQTT协议基础知识

文章目录 物联网IoT系列之MQTT协议基础知识物联网IoT是什么&#xff1f;什么是MQTT&#xff1f;为什么说MQTT是适用于物联网的协议&#xff1f;MQTT工作原理核心组件核心机制 MQTT工作流程1. 建立连接2. 发布和订阅3. 消息确认4. 断开连接 MQTT工作流程图MQTT在物联网中的应用 …

在Rocky Linux上安装Redis(DNF和源码安装)

一.前言 Redis 是一款高性能的 NoSQL 数据库&#xff0c;被广泛用于缓存、消息队列等场景。本教程将手把手教你如何在 Rocky Linux 上安装 Redis&#xff0c;包括使用 DNF 进行安装和源码编译安装的两种方式。 二. 使用 DNF 安装 Redis 1.安装redis sudo dnf -y install red…

江科大51单片机笔记【10】蜂鸣器(上)

一、蜂鸣器 1.原理 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常同来产生设备的按键音、报警音等提示信号蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器&#xff08;外观基本一样&#xff09;有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流…

Android设备是如何进入休眠的呢?

首先我们手机灭屏后&#xff0c;一般需要等一段时间CPU才真正进入休眠。即Android设备屏幕暗下来的时候&#xff0c;并不是立即就进入了休眠模式&#xff1b;当所有唤醒源都处于de-avtive状态后&#xff0c;系统才会进入休眠。在手机功耗中从灭屏开始到CPU进入休眠时间越短&…

011---UART协议的基本知识(一)

1. 摘要 文章为学习记录。主要介绍 UART 协议的概述、物理层、协议层、关键参数。 2. UART概述 通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;&#xff0c;通常称作UART&#xff08;串口&#xff09;&#xff0c;是一种异步****串…

共绘智慧升级,看永洪科技助力由由集团起航智慧征途

在数字化洪流汹涌澎湃的当下&#xff0c;企业如何乘风破浪&#xff0c;把握转型升级的黄金机遇&#xff0c;已成为所有企业必须直面的时代命题。由由集团&#xff0c;作为房地产的领航者&#xff0c;始终以前瞻视野引领变革&#xff0c;坚决拥抱数字化浪潮&#xff0c;携手数字…

【leetcode100】组合总和Ⅱ

1、题目描述 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 示例 1: 输入: candidates…

【cocos creator】热更新

一、介绍 试了官方的热更新功能&#xff0c;总结一下 主要用于安卓包热更新 参考&#xff1a; Cocos Creator 2.2.2 热更新简易教程 基于cocos creator2.4.x的热更笔记 二、使用软件 1、cocos creator v2.4.10 2、creator热更新插件&#xff1a;热更新manifest生成工具&…