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

23种设计模式——解释器模式(Interpreter Pattern)

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏:设计模式
✨特色专栏:知识分享
🥭本文内容:23种设计模式——解释器模式(Interpreter Pattern)
📚 ** ps **  :阅读文章如果有问题或者疑惑,欢迎在评论区提问或指出。


目录

一. 背景

二. 介绍

三. 主要角色

四. 代码示例

五. 应用场景

六. 优缺点

七. 总结


一. 背景

解释器模式对于很多人可能会感到陌生。但编程学习者对于解释这个词语的理解,可能会想到Python,因为它是解释型语言,可能有人也会想到正则表达式,因为它是解释器模式应用的典型案例。下面,将会对解释器模式进行详细的解释。


二. 介绍

解释器模式是一种行为型设计模式,它能让你定义一种语言的语法,并提供一个解释器来处理该语法。这种模式适用于你需要解析和执行特定语言或表达式的场景。

解释器模式主要用于处理像正则表达式、SQL 查询语句或者自定义 DSL(领域特定语言)等结构化文本。它的核心思想是将每个语法规则表示为一个类,从而构建出一个抽象语法树(AST)来表示复杂的句子。


三. 主要角色

AbstractExpression(抽象表达式):声明一个抽象的解释操作接口
TerminalExpression(终结符表达式):实现与文法中的终结符相关的解释操作
NonterminalExpression(非终结符表达式):实现与文法中的非终结符相关的解释操作
Context(上下文):包含解释器之外的一些全局信息
Client(客户端):构建表示文法定义的语言中特定句子的抽象语法树声明一个抽象的解释操作接口


四. 代码示例

下面是一个简单的计算器示例,展示了解释器模式的应用:

import java.util.HashMap;
import java.util.Map;// 抽象表达式
abstract class Expression {public abstract int interpret(Map<String, Integer> variables);
}// 变量表达式(终结符表达式)
class VariableExpression extends Expression {private String name;public VariableExpression(String name) {this.name = name;}@Overridepublic int interpret(Map<String, Integer> variables) {if (variables.containsKey(name)) {return variables.get(name);}throw new IllegalArgumentException("Variable not found: " + name);}
}// 常量表达式(终结符表达式)
class ConstantExpression extends Expression {private int value;public ConstantExpression(int value) {this.value = value;}@Overridepublic int interpret(Map<String, Integer> variables) {return value;}
}// 加法表达式(非终结符表达式)
class AddExpression extends Expression {private Expression left;private Expression right;public AddExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Map<String, Integer> variables) {return left.interpret(variables) + right.interpret(variables);}
}// 减法表达式(非终结符表达式)
class SubtractExpression extends Expression {private Expression left;private Expression right;public SubtractExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Map<String, Integer> variables) {return left.interpret(variables) - right.interpret(variables);}
}// 乘法表达式(非终结符表达式)
class MultiplyExpression extends Expression {private Expression left;private Expression right;public MultiplyExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret(Map<String, Integer> variables) {return left.interpret(variables) * right.interpret(variables);}
}// 解析器
class Parser {private String[] tokens;private int position;public Parser(String expression) {this.tokens = expression.split(" ");this.position = 0;}public Expression parse() {return parseExpression();}private Expression parseExpression() {Expression left = parseTerm();while (position < tokens.length && (tokens[position].equals("+") || tokens[position].equals("-"))) {String operator = tokens[position];position++;Expression right = parseTerm();if (operator.equals("+")) {left = new AddExpression(left, right);} else if (operator.equals("-")) {left = new SubtractExpression(left, right);}}return left;}private Expression parseTerm() {Expression left = parseFactor();while (position < tokens.length && tokens[position].equals("*")) {position++;Expression right = parseFactor();left = new MultiplyExpression(left, right);}return left;}private Expression parseFactor() {if (position >= tokens.length) {throw new IllegalArgumentException("Unexpected end of expression");}String token = tokens[position++];if (token.matches("[a-zA-Z]+")) {return new VariableExpression(token);} else if (token.matches("[0-9]+")) {return new ConstantExpression(Integer.parseInt(token));} else if (token.equals("(")) {Expression expr = parseExpression();if (position >= tokens.length || !tokens[position].equals(")")) {throw new IllegalArgumentException("Missing closing parenthesis");}position++;return expr;} else {throw new IllegalArgumentException("Unexpected token: " + token);}}
}// 客户端使用示例
public class InterpreterExample {public static void main(String[] args) {// 表达式: x + y * 2 - 3String expression = "x + y * 2 - 3";Parser parser = new Parser(expression);Expression expr = parser.parse();Map<String, Integer> variables = new HashMap<>();variables.put("x", 10);variables.put("y", 5);int result = expr.interpret(variables);System.out.println(expression + " = " + result); // 输出: x + y * 2 - 3 = 17// 更复杂示例: (x + y) * (z - 2)String complexExpression = "( x + y ) * ( z - 2 )";Parser complexParser = new Parser(complexExpression);Expression complexExpr = complexParser.parse();variables.put("z", 8);int complexResult = complexExpr.interpret(variables);System.out.println(complexExpression + " = " + complexResult); // 输出: ( x + y ) * ( z - 2 ) = 90}
}


五. 应用场景

与到类似下面的内容,我们可以使用解释器模式:

  1. 规则引擎:定义业务规则并解释执行
  2. 表达式计算器:数学表达式的计算
  3. SQL 解析器:数据库查询语句的解析
  4. 正则表达式引擎:匹配模式的解释执行
  5. 模板引擎:模板语言的解析和渲染

六. 优缺点

优点:

  • 易于改变和扩展文法:因为文法由类表示,所以可以使用继承来改变或扩展文法
  • 易于实现文法:每条文法规则都可以表示为一个类,因此相对容易实现
  • 复杂度易于控制:对于简单的文法,其实现可能过分简单;但对于复杂的文法,其复杂度会急剧增加

缺点:

  • 对于复杂的文法,维护工作变得困难
  • 执行效率较低:解释器模式通常使用大量的循环和递归调用,执行效率比其他设计模式低
  • 类膨胀问题:如果文法包含太多表达式类型,会导致系统出现大量细粒度的类

七. 总结

解释器模式适合在以下情况下使用:

  • 当有一个语言需要解释执行,并且可以将该语言的句子表示为抽象语法树时
  • 当该语言的文法较为简单时
  • 当效率不是关键考虑因素时

这个模式的关键在于将语言的文法规则分解成一组类,每个类代表一个语法结构,然后通过组合这些类来构建整个语法树。这使得添加新的语法元素变得更加容易,但可能会导致类的数量急剧增长。

http://www.dtcms.com/a/469287.html

相关文章:

  • 贴吧网站建设个人免费空间申请
  • 机器人能否实现远程视频通话方便家属探视老人
  • 小杰深度学习(ten)——视觉-经典神经网络——LetNet
  • LeetCode每日一题——困于环中的机器人
  • c++11 列表初始化 右值引用 移动语义 引用折叠 完美转发
  • 以太网与工业以太网通信C#开发
  • 14-verilog的SPI主驱动
  • vue项目安装chromedriver超时解决办法
  • 【C++】12.多态(超详解)
  • 【Linux操作系统】进程控制
  • 做实验流程图的网站广州免费核酸采集点时间
  • 网站网页设计公司电子商务公司logo
  • 潮玩盲盒抽赏小程序玩法拆解:不同视角下的增长逻辑分析
  • 使用Milvus和DeepSeek构建RAG demo
  • WD5030A,24V降5V,15A 大电流,应用于手机、平板、笔记本充电器
  • wordpress 新浪微博百度网站优化外包
  • Oracle LOB使用入门和简单使用,提供学习用的测试用例!
  • Java版旅游系统/文旅系统/旅游助手/旅游攻略/公众号/小程序/app全套源码
  • 线程2---javaEE(校招)
  • [创业之路-687]:华为“1+8+N”战略以及其背后的技术栈、商业逻辑。
  • 基于大语言模型(LLM)的城市时间、空间与情感交织分析:面向智能城市的情感动态预测与空间优化
  • 眼控交互:ErgoLAB新一代人机交互方式
  • 数字货币众筹网站开发如何做高网站的浏览量
  • 网站服务器频繁掉线的主要原因是什么
  • codeigniter换服务器之后,会员登录之后又跳回登录页面的解决方法
  • VS Code 的 SSH 密钥,并将其安全地添加到服务器
  • 香港服务器速度快慢受何影响?
  • 服务器相关:什么是 alios. centos. cuda. cuda tookit. gcc. cudann. pytorch.
  • K8S(五)—— K8s中YAML文件全方位解析:语法、案例、Port详解与快速编写技巧
  • 企业网站注销流程做企业网站需要服务器么