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

news2024/10/5 16:23:56

解释器

  • 是一种不常用的设计模式
  • 用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的解释器和解释器设计
  • 当我们需要开发一种新的语言时,可以考虑使用解释器模式
  • 尽量不要使用解释器模式,后期维护会有很大麻烦。在项目中,可以使用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):备忘录模式
          设计模式持续更新中…

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4月9日学习记录

[GXYCTF 2019]禁止套娃 涉及知识点&#xff1a;git泄露&#xff0c;无参数RCE 打开环境&#xff0c;源码什么的都没有&#xff0c;扫描后台看看 扫描发现存在git泄露 用githack下载查看得到一串源码 <?php include "flag.php"; echo "flag在哪里呢&#…

django之ajax

【一】前言 Ajax 异步提交局部刷新 发送请求的方式 浏览器地址栏直接输入url回车 GET请求a标签href属性 GET请求form表单 GET请求/POST请求ajax GET请求/POST请求 ​ AJAX 不是新的编程语言&#xff0c; 而是一种使用先有标准的新方法&#xff08;比如装饰器&#xff09; …

AtCoder ABC347 A-D题解

个人感觉这次D有点难。 比赛链接:ABC347 Problem A: 签到题。 #include <bits/stdc.h> using namespace std; int main(){int N,K;cin>>N>>K;for(int i1;i<N;i){int A;cin>>A;if(A%K0)cout<<A/K;}return 0; } Problem B: 主要考substr的…

unity按路径移动

using System; using System.Collections; using System.Collections.Generic; using UnityEngine;public class FollowPathMove : MonoBehaviour {public Transform[] wayPointArray;[SerializeField] private Transform PathA;//路径点的父物体[SerializeField]private Trans…

紫光展锐T610平台_4G安卓核心板方案定制开发

紫光展锐T610核心板配备Android 11操作系统&#xff0c;采用12nm制程工艺。该处理器CPU由2颗基于Cortex-A75架构的大核心和6颗基于Cortex-A55架构的小核心组成&#xff0c;最高主频为1.8GHz。GPU采用的是614.4MHz的Mali G52&#xff0c;可以流畅播放2400*1080分辨率视频&#x…

MacOS初识SIP——解决快捷指令sh脚本报错Operation not permitted

前言 因为一些原因&#xff0c;设计了一套快捷指令&#xff0c;中间涉及到一个sh脚本的运行&#xff0c;通过快捷指令运行时就会报错&#xff1a;operation not permitted 奇怪的是在快捷指令窗口下运行一切正常&#xff0c;但是从其他地方直接调用&#xff0c;例如通过Comma…

典型新能源汽车热管理系统方案分析

目前行业具有代表性的热管理系统有PTC电加热方案、热泵方案&#xff08;特斯拉八通阀热泵、吉利直接式热泵&#xff09;、威马的柴油加热方案以及以理想为代表的插电式混动车方案。 小鹏P7整车热管理方案分析&#xff08;PTC电加热方案&#xff09; 小鹏P7作为小鹏汽车的第2款…

免费Docker容器服务Koyeb和Zeabur介绍及推荐

想搭建个演示站点仅是演示用。在哪找免费的云服务&#xff1f;还是有很多的。前面介绍过replit&#xff0c;这里介绍下几个提供免费云服务的的PaaS平台Koyeb和Zeabur&#xff0c;Zeabur平台或许是最好的选择。比如把个人的博客免费部署上去&#xff0c;也是个不错的选择呢。 前…

JVM字节码与类的加载——类的加载过程详解

文章目录 1、概述2、加载(Loading)阶段2.1、加载完成的操作2.2、二进制流的获取方式2.3、类模型与Class实例的位置2.4、数组类的加载 3、链接(Linking)阶段3.1、链接阶段之验证(Verification)3.1.1、格式检查3.1.2、字节码的语义检查3.1.3、字节码验证3.1.4、符号引用验证 3.2、…

PVE下安装配置openwrt和ikuai

开端 openwrt 和 ikuai 是比较出名的软路由系统。我最早接触软路由还是因为我的一个学长要改自己家里的网络&#xff0c;使用软路由去控制网络。我听说后便来了兴致&#xff0c;也在我家搞了一套软路由系统。现在我已经做完了&#xff0c;就想着写个文章记录一下。 软路由简介…

GFS部署实验

目录 1、部署环境 ​编辑 2、更改节点名称 3、准备环境 4、磁盘分区&#xff0c;并挂载 5. 做主机映射--/etc/hosts/ 6. 复制脚本文件 7. 执行脚本完成分区 8. 安装客户端软件 1. 安装解压源包 2. 创建gfs 3. 安装 gfs 4. 开启服务 9、 添加节点到存储信任池中 1…

应急响应-拒绝服务钓鱼指南DDOS压力测试邮件反制分析应用日志

知识点 1、CC攻击分析 2、钓鱼邮件分析 3、内网渗透分析 一、演示案例-内网应急-日志分析-爆破 MSSQL-1433 SMB-445 二、演示案例-红队APT-钓鱼邮件-内容&发信人&附件 如何分析邮件安全性&#xff1a; 1、看发信人地址 2、看发信内容信息 3、看发信内容附件 看后…

2011年认证杯SPSSPRO杯数学建模B题(第一阶段)生物多样性的评估全过程文档及程序

2011年认证杯SPSSPRO杯数学建模 B题 生物多样性的评估 原题再现&#xff1a; 2010 年是联合国大会确定的国际生物多样性年。保护地球上的生物多样性已经越来越被人类社会所关注&#xff0c;相关的大规模科研和考察计划也层出不穷。为了更好地建立国际交流与专家间的合作&…

UML2.0在系统设计中的实际使用情况

目前我在系统分析设计过程中主要使用UML2.0来表达&#xff0c;使用StarUML软件做实际设计&#xff0c;操作起来基本很顺手&#xff0c;下面整理一下自己的使用情况。 1. UML2.0之十三张图 UML2.0一共13张图&#xff0c;可以分为两大类&#xff1a;结构图-静态图&#xff0c;行…

学习Rust的第一天:基础知识

Introduction 介绍 I am Shafin Murani is a software development student and I am documenting every single day of my progress in learning rust. This is the first article of the series. Shafin Muranishi 是一名软件开发专业的学生&#xff0c;这是他在30天内记录学…

苹果电脑(Mac)怎么清理 itunes 备份?

苹果电脑用户广泛利用 iTunes 应用程序对 iPhone 或 iPad进行定期备份&#xff0c;以确保珍贵的数据安全无虞。然而&#xff0c;随着备份历史的增长&#xff0c;它们会在磁盘上积累大量空间&#xff0c;尤其当您频繁为多台设备备份时&#xff0c;存储资源可能会迅速消耗殆尽。为…

Docker部署Logstash同步Mysql数据到ES

1、准备配置文件文件夹 2、部署logstash & elasticsearch docker pull docker.elastic.co/logstash/logstash:7.15.0 ## 替换{你的ES地址}为ES地址 docker run -d --name logstash -p 5044:5044 -p 9600:9600 -v D:\logstash\data\:/usr/share/logstash/data -v D:\logst…

服务器数据恢复—V7000存储raid5数据恢复案例

服务器数据恢复环境&#xff1a; P740AIXSybaseV7000存储阵列柜&#xff0c;阵列柜上有12块SAS机械硬盘&#xff08;包括1块热备盘&#xff09;。 服务器故障&#xff1a; 管理员在日常巡检过程中发现阵列柜中有一块磁盘发生故障&#xff0c;于是更换磁盘并同步数据&#xff0…

Kafka基础/1

Kafka 概念 Kafka 是一个分布式的流媒体平台。 应用&#xff1a;消息系统、日志收集、用户行为追踪、流式处理 特点&#xff1a;高吞吐量、消息持久化、高可靠性、高扩展性 术语&#xff1a; broker&#xff1a;Kafka 的服务器&#xff0c;Kafka 当中每一台服务器&#xf…

Visual Studio Code 终端为管理员权限

第一部 1、 Visual Studio Code 快捷方式启动选项加上管理员启动 第二步 管理员方式运行 powershell Windows 10的任务栏自带了搜索。或者开始菜单选搜索只需在搜索框中输入powershell。 在出来的搜索结果中右击Windows PowerShell&#xff0c;然后选择以管理员方式运行。 执…