设计模式(22):解释器模式

解释器

  • 是一种不常用的设计模式
  • 用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的解释器和解释器设计
  • 当我们需要开发一种新的语言时,可以考虑使用解释器模式
  • 尽量不要使用解释器模式,后期维护会有很大麻烦。在项目中,可以使用jruby、groovy、java的js引擎来替代解释器的作用,弥补java语言的不足。

开发中常见的场景

  • EL表达式的处理
  • 正则表达式解释器
  • SQL语法的解释器
  • 数学表达式解释器

举例代码实现

  • 解析和执行数学表达式
    输入"5+4*5-8/4",输出“23”
  • 抽象解释器接口
/**
 * 抽象解释器接口
 */
public interface Expression {
	int interpret(Context context);
}
  • 终结符表达式
/**
 * 数值表达式---终结符表达式
 */
public class NumberExpression implements Expression{
	private Integer number;
	public NumberExpression(Integer number) {
		super();
		this.number = number;
	}
	@Override
	public int interpret(Context context) {
		return number;
	}
}
/**
 * 运算符号表达式---终结符表达式
 * 	symbol:
 * 		1:加 
 * 		2:减 
 * 		3:乘 
 * 		4:除 
 */
public class SymbolExpression implements Expression {
	private int symbol;	
	public SymbolExpression(int symbol) {
		super();
		this.symbol = symbol;
	}
	@Override
	public int interpret(Context context) {
		return symbol;
	}
}
  • 非终结符表达式
/**
 * 加法表达式——加法表达式也是数值表达式的一种
 */
public class AdditionExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public AdditionExpression(NumberExpression left, NumberExpression right) {
		super(1);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) + right.interpret(context);
	}
}
/**
 * 减法表达式---减法表达式也是数值表达式的一种
 */
public class SubtractExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public SubtractExpression(NumberExpression left, NumberExpression right) {
		super(2);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) - right.interpret(context);
	}
}
/**
 * 乘法表达式——乘法表达式也是数值表达式的一种
 */
public class MultiplicationExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public MultiplicationExpression(NumberExpression left, NumberExpression right) {
		super(3);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) * right.interpret(context);
	}
}
/**
 * 除法表达式——除法表达式也是数值表达式的一种
 */
public class DivisionExpression extends NumberExpression{
	private NumberExpression left;
	private NumberExpression right;
	public DivisionExpression(NumberExpression left, NumberExpression right) {
		super(4);
		this.left = left;
		this.right = right;
	}
	@Override
	public int interpret(Context context) {
		return left.interpret(context) / right.interpret(context);
	}
}
  • 上下文类(context)
public class Context {
	
	private Expression expression;
	
	public Context(String expression) {
		LinkedList<Expression> linkedList = new LinkedList<Expression>();
		int num = 0;
		for(int i=0;i<expression.length();i++) {
			char ati;
			if((ati=expression.charAt(i))>='0' && ati<='9') {
				num = num*10 + (ati-'0');
			}else {
				Expression peek;
				SymbolExpression symbol;
				NumberExpression left,right;
				if(!linkedList.isEmpty() && (
					(peek=linkedList.peekLast()) instanceof SymbolExpression) 
					&& (peek.interpret(this)==3 || peek.interpret(this)==4)
					){
					symbol = (SymbolExpression)linkedList.pollLast();
					left = (NumberExpression)linkedList.pollLast();
					right = new NumberExpression(num);
					if(symbol.interpret(this)==3){
						linkedList.addLast(new MultiplicationExpression(left, right));
					}else{
						linkedList.addLast(new DivisionExpression(left, right));
					}
				}else{
					linkedList.addLast(new NumberExpression(num));
				}
				SymbolExpression symbolExpression = null;
				switch (ati) {
				case '+':
					symbolExpression = new SymbolExpression(1);
					break;
				case '-':
					symbolExpression = new SymbolExpression(2);
					break;
				case '*':
					symbolExpression = new SymbolExpression(3);
					break;
				case '/':
					symbolExpression = new SymbolExpression(4);
					break;
				default:
					break;
				}
				num = 0;
				linkedList.addLast(symbolExpression);
			}
		}
		Expression peek;
		if(!linkedList.isEmpty() &&(	
				(peek=linkedList.peekLast()) instanceof SymbolExpression) 
					&& (peek.interpret(this)==3 || peek.interpret(this)==4)
		 	){
			Expression symbol = linkedList.pollLast();
			NumberExpression left = (NumberExpression)linkedList.pollLast();
			NumberExpression right = new NumberExpression(num);
			if(symbol.interpret(this)==3){
				linkedList.addLast(new MultiplicationExpression(left, right));
			}else{
				linkedList.addLast(new DivisionExpression(left, right));
			}
		}else{
			linkedList.add(new NumberExpression(num));
		}
		init(linkedList);
	}
	private void init(LinkedList<Expression> linkedList){
		SymbolExpression symbolExpression = null;
		NumberExpression left = null;
		while(!linkedList.isEmpty()){
			Expression tempExpression = linkedList.pollFirst();
			if(tempExpression instanceof SymbolExpression){
				symbolExpression = (SymbolExpression)tempExpression;
			}else{
				if(left==null){
					left = (NumberExpression)tempExpression;
				}else{
					NumberExpression right = (NumberExpression)tempExpression;
					switch (symbolExpression.interpret(this)) {
					case 1:
						left = new AdditionExpression(left, right);
						break;
					case 2:
						left = new SubtractExpression(left, right);
						break;
					case 3:
						left = new MultiplicationExpression(left, right);
						break;
					case 4:
						left = new DivisionExpression(left, right);
						break;
					default:
						break;
					}
				}
			}
		}
		this.expression = left;
	}
	public int calculate(){
		return this.expression.interpret(this);
	}
}
  • 客户端调用
public static void main(String[] args) {
	Context context = new Context("33+12*9+42/2+6/3");
	int calculate = context.calculate();
	System.out.println(calculate);
}
  • 结果
    在这里插入图片描述





更多设计模式学习:

          设计模式(1):介绍
          设计模式(2):单例模式
          设计模式(3):工厂模式
          设计模式(4):建造者模式
          设计模式(5):原型模式
          设计模式(6):桥接模式
          设计模式(7):装饰器模式
          设计模式(8):组合模式
          设计模式(9):外观模式
          设计模式(10):享元模式
          设计模式(11):适配器模式
          设计模式(12):代理模式
          设计模式(13):模板方法模式
          设计模式(14):命令模式
          设计模式(15):迭代器模式
          设计模式(16):观察者模式
          设计模式(17):中介者模式
          设计模式(18):状态模式
          设计模式(19):策略模式
          设计模式(20):责任链模式
          设计模式(21):备忘录模式
          设计模式持续更新中…

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

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

相关文章

【Redis】持久化

文章目录 一、RDB1.1、RDB的自动备份与手动备份1.1.1、自动备份1.1.2、手动备份 1.2、RDB优点1.3、RDB缺点1.4、RDB快照1.5、RDB优化配置项 二、AOF2.1、AOF工作流程2.2、AOF写回策略2.3、MP-AOF实现2.4、AOF优缺点2.5、AOF重写机制 三、RDBAOF混合持久化3.1、数据恢复顺序和加…

阿里云OSS使用流程

准备工作 无论怎么样&#xff0c;你需要准备一个阿里云账号&#xff0c;点击&#xff1a;注册阿里云 输入相关信息&#xff0c;然后注册成功以后&#xff0c;点击 然后注册成功了&#xff0c;实名一下阿里云账号。打开实名入口&#xff0c;选择个人实名或者企业实名。 如果你…

windows wireshark抓包rtmp推流出现TCP Retransmission

解决办法&#xff1a;tcp.port1935 && !(tcp.analysis.retransmission)

签名失败当前系统没有安装苹果根证书

发生背景 第一次我没有iOS证书(.p12)和描述文件(.mobileprovision)。按照这个文档https://ask.dcloud.net.cn/article/152拿到后&#xff0c;安心打包出问题。 错误信息 [Info] begin getCertCName... [Info] begin codesignFramwork to ipa... [Error] DCUniBase.framework…

设计模式系列:单例模式

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;WPS二次开发QQ群:250325397&#xff09;&#xff0c;摸鱼吹牛嗨起来&#xff01…

RabbitMQ如何保证消息的幂等性???

在RabbitMQ中&#xff0c;保证消费者的幂等性主要依赖于业务设计和实现&#xff0c;而非RabbitMQ本身提供的一种直接功能。 在基于Spring Boot整合RabbitMQ的场景下&#xff0c;要保证消费者的幂等性&#xff0c;通常需要结合业务逻辑设计以及额外的技术手段来实现。以下是一个…

嵌入式学习51-单片机4

知识零碎&#xff1a; nop空指令 CRC校验 为了保证51单片与温度传感18b20 之间的高电平 采用一个上拉电阻改变电平的高低 温度寄存器原理

react17+antd4 动态渲染导航菜单中的icon

在路由信息对照表中的icon可以有两种形式&#xff1a;一种是组件形式&#xff0c;一种是字符串形式的。 在antd4的Menu.Item和SubMenu中的icon属性的格式为&#xff1a; 1.组件形式 这种方法在渲染时很方便&#xff0c;与antd中的Menu.Item中的icon属性的形式是一致的&#…

51单片机+TN901非接触式红外测温设计论文与源码PCB等资料

1、摘要 温度测量技术应用十分广泛&#xff0c;而且在现代设备故障检测领域中也是一项非常重要的技术。但在某些应用领域中&#xff0c;要求测量温度用的传感器不能与被测物体相接触&#xff0c;这就需要一种非接触的测温方式来满足上述测温需求。本论文正是应上述实际需求而设…

如何让MacOS「终端」走代理

在 MacOS 操作系统中&#xff0c;默认情况下&#xff0c;终端命令行不会通过代理进行网络连接。这导致在应用软件研发过程中&#xff0c;许多需要通过命令行下载安装的软件或依赖包无法成功安装。经常出现Failed to connect to xxx port 443 after 75329 ms: Couldnt connect t…

【资源分享】MAC上最好用的截图软件-Snipaste

::: block-1 “时问桫椤“是一个关注本科生到研究生教育阶段的不严肃的公众号&#xff0c;希望能在大家迷茫、难受、困难之时帮助到大家。用广大研究生的经验总结&#xff0c;让大家能尽早的适应研究生生活&#xff0c;尽快的看透科研本质。祝好&#xff01;&#xff01;&#…

OLAP在线实时 数据分析平台

随着业务的增长&#xff0c;精细化运营的提出&#xff0c;产品对数据部门提出了更高的要求&#xff0c;包括需要对实时数据进行查询分析&#xff0c;快速调整运营策略&#xff1b;对小部分人群做 AB 实验&#xff0c;验证新功能的有效性&#xff1b;减少数据查询时间&#xff0…

IntelliJ IDEA 2024.1安装与激活[破解]

一&#xff1a;IDEA官方下载 ①如题&#xff0c;先到IDEA官方下载&#xff0c;简简单单 ②IDEA官方&#xff1a;IntelliJ IDEA – the Leading Java and Kotlin IDE 二&#xff1a;获取脚本 &#x1f31f;网盘下载&#xff1a;jetbra (密码&#xff1a;lzh7) &#x1f31f;获取…

macOS制作C/C++ app

C/C制作macOS .app 一、 .app APP其实是一个文件夹结构&#xff0c;只不过mac的界面中让它看起来像一个单独的文件。 在shell终端或者右键查看包结构即可看到APP的目录结构。 通常的app目录结构如下&#xff1a; _CodeSignature, CodeResources 一般为Mac APP Store上架程序…

Redis的RDB文件

Redis持久化 Redis是操作内存的&#xff0c;所以是内存数据库&#xff0c;断电即失&#xff0c;所以需要持久化 RDB 文件名:dump.rdb # The filename where to dump the DB dbfilename dump.rdb在指定时间间隔内&#xff0c;将内存中的数据&#xff0c;集体快照写入磁盘内&…

FineBI概述

FineBI是一款商业智能&#xff08;Business Intelligence&#xff09;工具&#xff0c;它通过最终业务用户自主分析企业已有的信息化数据&#xff0c;帮助企业发现并解决存在的问题&#xff0c;协助企业及时调整策略做出更好的决策&#xff0c;增强企业的可持续竞争性。它以自助…

HDFS读、写数据流程(图解)以及元数据的checkpoint机制

一、HDFS概述 HDFS集群由NameNode,DataNode,SecondaryNameNode构成。 NameNode&#xff1a;接受用户请求。存储元数据&#xff08;描述文件的数据&#xff0c;如文件名、文件大小、目录名、文件创建时间等&#xff09; DataNode&#xff1a;负责管理用户的文件数据块&#xff0…

openGauss学习笔记-259 openGauss性能调优-使用Plan Hint进行调优-指定不使用全局计划缓存的Hint

文章目录 openGauss学习笔记-259 openGauss性能调优-使用Plan Hint进行调优-指定不使用全局计划缓存的Hint259.1 功能描述259.2 语法格式259.3 示例 openGauss学习笔记-259 openGauss性能调优-使用Plan Hint进行调优-指定不使用全局计划缓存的Hint 259.1 功能描述 全局计划缓…

Linux内核之原子操作atomic_t用法实例(三十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

MYSQL 8.0版本修改用户密码(知道登录密码)和Sqlyog错误码2058一案

今天准备使用sqlyog连接一下我Linux上面的mysql数据库&#xff0c;然后就报如下错误 有一个简单的办法就是修改密码为password就完事!然后我就开始查找如何修改密码! 如果是需要解决Sqlyog错误码2058的话&#xff0c;执行以下命令&#xff0c;但是注意root对应host是不是loca…