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

设计模式----解释器模式

一、简介

        解释器模式使用频率并不高,通常用来构建一个简单语言的语法解释器,它只在一些非常特定的领域被用到,比如编译器、规则引擎、正则表达式、sql解析等。

        解释器模式是行为型设计模式之一,它的原始定义为:用于定义语言语法规则表示,并提供解释器来处理句子中的语法。

        我们通过一个例子来解释下解释器模式,假设我们设计一个软件来进行加减计算,我们第一想法就是使用工具类,提供对应的加法和减法的工具方法。

public int add(int a,int b){
return a+b;
}public int add(int a,int b,int c){
return a+b+c;
}
......

上面的形式比较单一、有限如果形式变化非常多,这就不符合要求,因为加法和减法运算,两个运算符数组可以有无限种合作方式,比如1+3+2+1-5....

        解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。

二、结构

        解释器模式由以下几种角色组成:

        ①抽象表达式角色:定义解释器的接口,约定解释器的操作,主要包含解释方法interoret

        ②终结符表达式角色:用来实现文发中与终结符相关的操作,文法中的每一个终结符都有一个具体的终结符表达式与之对应

        ③非终结符表达式:用来实现文法中与非终结符相关的操作,文法中每条规则都对应一个非终结符表达式

        ④上下文类:通常包含各个解释器需要的数据或者是公共的功能,一般用来传递所有解释器共享的数据。

三、实现

        我们定义一个进行加减乘除计算的语言,语法规则如下:

        ①运算符只包含加减乘除,并且没有优先级概念

        ②表达式中,先写数字后写运算符,空格隔开

// 表达式接口
public interface Expression {int interpret();
}// 加法解释器
public class AddExpression implements Expression {private Expression left;private Expression right;public AddExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() + right.interpret();}
}// 减法解释器
public class SubtractExpression implements Expression {private Expression left;private Expression right;public SubtractExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() - right.interpret();}
}// 乘法解释器
public class MultiplyExpression implements Expression {private Expression left;private Expression right;public MultiplyExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {return left.interpret() * right.interpret();}
}// 除法解释器
public class DivideExpression implements Expression {private Expression left;private Expression right;public DivideExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic int interpret() {try {return left.interpret() / right.interpret();} catch (ArithmeticException e) {System.out.println("除数不能为0");return -1;}}
}// 数字解释器
public class NumberExpression implements Expression {private int number;public NumberExpression(int number) {this.number = number;}@Overridepublic int interpret() {return number;}
}

现在我们可以使用这些类来解析四则运算表达式了。例如,对于表达式 “1 + 2 * 3 - 4 / 2”我们可以使用以下代码来解析该表达式:

Expression expression = new SubtractExpression(new AddExpression(new NumberExpression(1),new MultiplyExpression(new NumberExpression(2),new NumberExpression(3))),new DivideExpression(new NumberExpression(4),new NumberExpression(2)));
int result = expression.interpret();
System.out.println("计算结果为:" + result);

四、总结

优点

①易于改变可扩展文法,因为在解释器模式中实用类来表示语言的文法规则的,因此可以通过继承等机制改变或扩展文法,每一个文法规则都可以表示为一个类,因此我们可以快速的实现一个迷你的语言

②实现文法比较容易,在抽像语法术中每一个表达式节点的实现方式都是相似的,这些代码不特别复杂

③增加新的解释表达式比较方便,如果用户增加新的解释表达式,只需要对应增加一个新的表达式类就可以,原有的表达式不需修改,符合开闭原则

缺点

①对于复杂文法难以维护,在解释器中,一条规则至少要定义一个类,因此一个语言中有太多的文法规则,那么就会使类的个数急剧增加,导致系统的维护难以管理。

②执行效率低,在解释器模式中,大量的使用循环和递归调用,所以复杂的句子执行起来比较繁琐

使用场景

①当语言的文法比较简单时,并且执行的效率不是关键问题的时候

②当问题重复出现,且可以用一种简单的语言来表达

③当一个语言要解释执行,并且语言中的句子可以表示为一个抽象的语法树的时候。

http://www.lryc.cn/news/266122.html

相关文章:

  • Linux常用命令(一):Conda、RPM、文件权限、apt-get(更新中...
  • 3 个适用于 Mac 电脑操作的 Android 数据恢复最佳工具 [附步骤]
  • 日志服务 SLS 深度解析:拥抱云原生和 AI,基于 SLS 的可观测分析创新
  • MinIO客户端之rm
  • 【Linux笔记】文件和目录操作
  • Vue-router 中hash模式和history模式的区别
  • Debian在升级过程中报错
  • IOS开发问题记录
  • 数据流图_DFD图_精简易上手
  • 使用 Xcode 创建一个新的项目并运行
  • 教师未来前景发展
  • 【华为机试】2023年真题B卷(python)-采样过滤
  • 编译opencv和opencv_contrib
  • 每次maven刷新jdk都要重新设置
  • 《PySpark大数据分析实战》-18.什么是数据分析
  • 【小白攻略】php 小数转为百分比,保留两位小数的函数
  • electron GPU process isn‘t usable. Goodbye
  • ApsaraMQ Serverless 演进之路,助力企业降本
  • redis 从0到1完整学习 (六):Hash 表数据结构
  • 阿里云江苏省中小企业补贴5000元上云补贴金
  • PID算法
  • Linux bridge开启hairpin模拟测试macvlan vepa模式
  • 连续执行函数和alert与focus死循环事件
  • 向量投影:如何将一个向量投影到矩阵的行向量生成子空间?
  • Ubuntu18.04安装GTSAM库(亲测可用)
  • SpringBoot中常见配置配置,MySQL、Redis、MinIO等
  • 面向LLM的App架构——技术维度
  • ArkUI - 状态管理
  • C++ 学习系列 -- C++ 中的多态行为
  • Spring Cloud中实现Feign声明式服务调用客户端