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

【再探】设计模式—备忘录模式与解释器模式

 备忘录模式是用于保存对象在某个时刻的状态,来实现撤销操作。而解释器模式则是将文本按照定义的文法规则解析成对应的命令。

1 备忘录模式

需求:保存对象在某个时刻的状态,后面可以对该对象实行撤销操作。

1.1 备忘录模式介绍

提供一种状态恢复机制,在不破坏封装的前提下,捕获对象内部状态并在该对象之外保存这个状态。可以在以后将对象恢复到原先保存的状态。

图 备忘录模式 UML

public class MementoPattern {public static void main(String[] args) {String[] colors = {"red","blue","green","pink","black"};Button button = new Button();Random random = new Random();MementoCareTaker<ButtonMemento> careTaker = new MementoCareTaker<>();for (int i = 0; i < 10; i++) {button.setColor(colors[random.nextInt(colors.length)]);button.setPositionX(random.nextDouble());careTaker.pushMemento(button.createMemento());}button.restoreFromMemento(careTaker.getMemento(2));System.out.println(button);button.restoreFromMemento(careTaker.getMemento(3));System.out.println(button);button.restoreFromMemento(careTaker.getMemento(1));System.out.println(button);}private static class Button {private String color;private Double positionX;public String getColor() {return color;}public void setColor(String color) {this.color = color;}public Double getPositionX() {return positionX;}public void setPositionX(Double positionX) {this.positionX = positionX;}public ButtonMemento createMemento() {return new ButtonMemento(color,positionX);}public void restoreFromMemento(ButtonMemento memento) {this.color = memento.getColor();this.positionX = memento.positionX;;}@Overridepublic String toString() {return "Button{" +"color='" + color + '\'' +", positionX=" + positionX +'}';}}private static class ButtonMemento {private final String color;private final Double positionX;public ButtonMemento(String color, Double positionX) {this.color = color;this.positionX = positionX;}public String getColor() {return color;}public Double getPositionX() {return positionX;}}private static class MementoCareTaker<T> {private final Stack<T> stack = new Stack<>();public void pushMemento(T t) {stack.push(t);}public T getMemento(int num) {T t = null;while (num-- > 0 && !stack.isEmpty()) {t = stack.pop();}return t;}}}

1.2 优缺点

优点:

  1. 提供了一种状态恢复机制,对象可以方便地回到一个特定的历史步骤状态。

缺点:

  1. 需要保存不同时刻的对象状态,这将耗费许多内存等资源。
  2. 类的数量增多,当对象自带有变动时,对应的备忘类也需要修改。

2 解释器模式

需求:将文本按照特定的语法规则转换成计算机中特定的命令。

2.1 解释器模式介绍

定义一个语言的文法,并建立一个解释器来解释该语言中的句子。这里的“语言”是指使用特定格式和语法的代码。

图 解释器UML

这里的Context 一般用于存储解释器之外的一些全局信息,也可以省略这个类。

::=

定义为。

|

或。

 ‘{’和‘}’

组合。

*

出现0或多次。

语言单位

语言构造成分,每一条语句所定义的字符串。

终结表达式

组成元素是最基本的语言单位,不能在进行分解。

非终结表达式

组成元素仍可以是表达式,可进一步分解。

图 文法规则说明

public class InterpreterPattern {/*** 语法规则:* value ::= a integer* operator ::= '+' | '-' | '*' | '/'* expression ::= value operator value | complexExpression* complexExpression ::= expression operator expression | expression operator (expression)*/public static void main(String[] args) {String[] textArr = {"1+4*3","4*5+3","(3+4)*23", "(3+24)-(23-8)", "(2-3)*(24+2*3)", "(((1+2)*(2+3)))+32"};for (int i = 0; i < textArr.length; i++) {System.out.print(textArr[i]);System.out.println("=" + new ComplexExpression().interpreter(textArr[i]));}}private static abstract class Expression {abstract int interpreter(String text);protected int compute(int leftNum,int rightNum,char opera) {switch (opera) {case '+': return leftNum + rightNum;case '-': return leftNum - rightNum;case '*': return leftNum * rightNum;case '/': return leftNum / rightNum;}return 0;}}/*** 复杂表达式*/private static class ComplexExpression extends Expression {@Overrideint interpreter(String text) {
//            System.out.println("ComplexExpression:" + text);int letNum=0;int rightNum=0;char opera = ' ';Pattern pattern = Pattern.compile("[\\+\\-\\*\\/]");Matcher matcher = pattern.matcher(text);if (matcher.find()) {int start = matcher.start();opera = text.charAt(start);if (text.indexOf("(") == 0) { // 在操作符前面有括号, 先计算括号的内容int endBracketPos = findEndBracketPos(text);letNum = new ComplexExpression().interpreter(text.substring(1,endBracketPos));if (endBracketPos == text.length() -1 ) {return letNum;}opera = text.charAt(endBracketPos+1);rightNum = new ComplexExpression().interpreter(text.substring(endBracketPos+2));} else if ((opera == '*' || opera == '/') && text.charAt(start+1) != '(') { // 需要先完成左边运算boolean hasNext = matcher.find(start + 1);if (hasNext) {int pos2 = matcher.start();letNum = new ComplexExpression().interpreter(text.substring(0,pos2));opera = text.charAt(pos2);rightNum = new ComplexExpression().interpreter(text.substring(pos2+1));} else {letNum = new TerminalExpression().interpreter(text.substring(0,start));rightNum = new ComplexExpression().interpreter(text.substring(start+1));}} else {letNum = new TerminalExpression().interpreter(text.substring(0,start));rightNum = new ComplexExpression().interpreter(text.substring(start+1));}return compute(letNum,rightNum,opera);} else { // 终结表达式return new TerminalExpression().interpreter(text);}}private int findEndBracketPos(String text) {int startPos = 0,endPos = 0;do {endPos = text.indexOf(")",endPos+1);startPos = text.indexOf("(",startPos+1);} while (startPos < endPos && startPos > 0);return endPos;}}/*** 是一个数值 或者 是 (数值) 形式,要把text 转换为数值*/private static class TerminalExpression extends Expression {@Overrideint interpreter(String text) {
//            System.out.println("TerminalExpression:" + text);if (text.indexOf("(") == 0) {text = text.substring(1,text.length() - 1);}return Integer.parseInt(text);}}}

2.2 优缺点

优点:

  1. 实现文法较为容易。易于改变和扩展文法。增加新的解释表达式较为方便,只需增加相关表达式类即可,符合开闭原则。

缺点:

  1. 执行效率较低,使用了大量的循环和递归调用,调试过程比较麻烦。
  2. 复杂文法难以维护。如果一种语言包含太多文法规则,类的数量将会急剧增加,导致系统难以管理和维护。

相关文章:

【再探】设计模式—备忘录模式与解释器模式

备忘录模式是用于保存对象在某个时刻的状态&#xff0c;来实现撤销操作。而解释器模式则是将文本按照定义的文法规则解析成对应的命令。 1 备忘录模式 需求&#xff1a;保存对象在某个时刻的状态&#xff0c;后面可以对该对象实行撤销操作。 1.1 备忘录模式介绍 提供一种状…...

SpringCloud网关-gateway

一 什么是网关&#xff1f;为什么选择 Gateway? 网关功能如下&#xff1a; 身份认证和权限校验服务路由、负载均衡请求限流 在 Spring Cloud 中网关的实现包含两种&#xff1a; Gateway&#xff08;推荐&#xff09;&#xff1a;是基于 Spring5 中提供的 WebFlux &#xff…...

LiveData是如何感知Room数据变化的

一 Room数据变化LiveData如何收到onChanged回调的&#xff1f; 1.1 LiveData是如何创建的 这里讨论的LiveData的创建是特指Dao定义的方法的返回类型&#xff0c;而不是所有的LiveData。 以NoteDao 举例&#xff1a; Dao public interface NoteDao {Query("select * fr…...

【自动化】WebUI自动化通过读取用户数据的方式启动浏览器实现绕过相关登录验证的方法。

背景说明 我相信做自动化测试或者实现UI自动化相关功能的同学肯定碰到过&#xff0c;每次写好脚本执行时都是默认打开一个 “新”的浏览器&#xff0c;我的意思是就跟刚下载的浏览器一样。而不是平时日常使用着的浏览器的状态&#xff0c;日常使用浏览器时只要近期登录过&…...

信号:干扰类别及特征提取

目录 第一部分&#xff1a;干扰类别 1.压制干扰 1.1噪声调幅瞄准式干扰(单音干扰) 1.2噪声调频阻塞式干扰&#xff08;宽带噪声干扰&#xff09; 1.3噪声调频扫频式干扰&#xff08;线性调频&#xff09; 2.欺骗干扰 2.1距离欺骗干扰&#xff08;幅度调制干扰&#xff0…...

【推荐】用scss循环zoom缩放比例,解决可视化大屏在不同分辨率屏幕下的适配问题

方法1&#xff1a; 指定几种常规屏幕宽度&#xff08;用这种方式就必须要强制用户全屏查看页面&#xff0c;在固定的宽度下才能达到比较不错的显示效果&#xff09; // 适配不同分辨率的页面---------------------------------------- html {overflow: hidden;width: 1920px;…...

23中设计模式之一— — — —命令模式的详细介绍

命令模式 Command Pattern讲解 概念描述模式结构主要角色模式的UIM类图模式优点模式缺点应用场景实例演示类图代码演示运行结果 概念 命令模式&#xff08;别名&#xff1a;动作&#xff0c;事务&#xff09; 命令模式是一种行为设计模式&#xff0c;将一个请求封装为一个对象…...

解决 Mac Django 连接Mysql 出现 image not found 问题

最近在使用 Django 框架&#xff0c;因为升级到4.2版本了&#xff0c;对应的本机 Mysql 5.7 就不适用了&#xff0c;于是升级到了 Mysql 8.0&#xff0c;写好代码之后出现如下错误&#xff1a; 仔细分析一下错误的描述&#xff1a; ImportError: dlopen(/Library/Frameworks/P…...

EitbaseEX香港业务开展,提升用户友好交易体验

在全球范围内备受瞩目的加密货币交易平台Coinbase&#xff0c;宣布正式入驻香港市场&#xff0c;并命名为EitbaseEX。这一战略性扩展举措&#xff0c;旨在为香港提供先进的加密货币交易技术和服务&#xff0c;同时将香港打造为其在亚太地区的重要枢纽。 作为国际金融中心&#…...

ROS学习记录:自定义消息类型

前言 当我们需要传输一些特殊的数据时&#xff0c;且官方的消息包无法满足需求&#xff0c;我们便可以自己定义一个消息类型。 实验步骤 一、在终端输入cd ~/catkin_ws1/src进入工作空间中src目录 二、输入catkin_create_pkg qq_msgs roscpp rospy std_msgs message_generati…...

创新实训2024.06.06日志:部署web服务

1. 运行web项目前后端服务 首先我们要先在服务器上运行客户端以及服务端的应用程序。随后再考虑如何通过公网/局域网访问的问题。 如何启动服务在仓库对应分支下的Readme文件中已经有详细描述了。 1.1. 启动服务端 对于服务端&#xff0c;即&#xff08;要求你在服务端子项…...

使用C++实现YOLO图像分类:从环境搭建到性能评估的完整指南

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…...

Linux中安装Docker,并使用Docker安装MySQL和Redis

1、安装docker 1卸载系统之前的docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2、安装Docker-CE #安装必须的依赖 sudo yum install -y yum-utils \device-map…...

期货短线交易的核心技术是什么

一、市场分析是短线交易的基础&#xff1a; 技术分析在短线交易中尤为重要&#xff0c;包括K线图、均线系统、成交量与持仓量等指标。K线图可以帮助交易者识别关键价格形态和趋势线&#xff0c;从而判断市场走势。均线系统则可以利用短期均线交叉作为买卖信号&#xff0c;如金…...

VSCode+Vite+Vue3断点调试

目录 lunch.json创建 vite.config.ts 打断点运行 lunch.json创建 首先&#xff0c;点击VSCode左上角&#xff0c;甲壳虫运行的按钮&#xff0c;然后点击运行与调试&#xff0c;选择chrome浏览器&#xff0c;修改成一下配置。 { // 使用 IntelliSense 了解相关属性。 // 悬停…...

RPC框架原理(一)

RPC框架原理 网络和IO的关系&#xff0c;IO&#xff08;input和output&#xff09;面向的是谁&#xff1f;OSI 7层参考模型&#xff0c;TCP/IP协议为什么会出现一个会话层三次握手socket心跳keep alive四次挥手 网络IO&#xff08;IO模型&#xff09; IO框架底层 学习顺序&…...

LCTF 2018 bestphp‘s revenge

考点:Soap原生类Session反序列化CRLF注入 <?php highlight_file(__FILE__); $b implode; call_user_func($_GET[f], $_POST); session_start(); if (isset($_GET[name])) { $_SESSION[name] $_GET[name]; } var_dump($_SESSION); $a array(reset($_…...

MySQL主从搭建--保姆级教学

MYSQL主从搭建步骤 主节点 # 进入目录 cd /opt# 下载安装包 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz# 解压 tar -xvf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz# 拷贝到/usr/local mv /opt/mysql-8.0.20-linux-g…...

Modbus通信协议--RTU

一、RTU介绍 MODBUS协议支持多种功能码&#xff0c;不同的功能码对应不同的操作&#xff1a; 0x01读线圈状态0x02读离散输入状态0x03读保持寄存器0x04读输入寄存器0x05写单个线圈0x06写单个保持寄存器0x0F写多个线圈0x10写多个保持寄存器 二、实验 1.0x03功能码读单个保持寄…...

我是大学生,应该选系统运维方向,还是web开发方向?

选择系统运维方向还是Web开发方向取决于你的兴趣、职业目标和个人技能。以下是对这两个方向的详细对比和建议&#xff0c;帮助你做出更明智的选择 双方比较 &#x1f926;‍♀️系统运维方向 优点&#xff1a; 稳定性&#xff1a;系统运维工作通常比较稳定&#xff0c;许多…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...