【设计模式——学习笔记】23种设计模式——备忘录模式Memento(原理讲解+应用场景介绍+案例介绍+Java代码实现)

案例引入

游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,可以从备忘录对象恢复到大战前的状态

传统设计方案

针对每一种角色,设计一个类来存储该角色的状态

【分析】

  • 一个对象,就对应一个保存对象状态的对象, 这样当我们游戏的对象很多时,不利于管理,开销也很大
  • 传统的方式是简单地做备份,new出另外一个对象出来,再把需要备份的数据放到这个新对象,但是这样暴露了对象内部的细节
  • 优化方式:使用备忘录模式

介绍

基本介绍

  • 备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
  • 可以这样理解备忘录模式: 现实生活中的备忘录是用来记录某些要去做的事情或者是记录已经达成的共同意见的事情,以防忘记。而在软件层面,备忘录对象主要用来记录一个对象的某种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作
  • 备忘录模式属于行为型模式

登场角色

在这里插入图片描述

  • Originator(生成者):Originator角色会在保存自己的最新状态时生成Memento角色。当把以前保存的Memento角色传递给Originator角色时,它会将自已恢复至生成该Memento角色时的状态
  • Memento(备忘录):Memento角色会将Originator 角色的内部信息整合在一起。在 Memento 角色中虽然保存了Originator 角色的信息,但它不会向外部公开这些信息(通过对方法的权限字符进行设置)
  • Caretaker(负责人):当Caretaker角色想要保存当前的Originator角色的状态时,会通知Originator角色Originator角色在接收到通知后会生成Memento角色的实例并将其返回给Caretaker角色。由于以后可能会用Memento实例来将Originator恢复至原来的状态,因此Caretaker角色会一直保存 Memento实例在示例程序中。Caretaker角色只能使用Memento角色的两种接口(API)中的窄接口,也就是说它无法访问Memento角色内部的所有信息(比如案例三中Caretaker角色只能获取Memento角色的金钱信息,无法进行创建Memento实例等操作)。它只是将Originator角色生成的Memento角色当作一个黑盒子保存起来。虽然Originator角色Memento角色之间是强关联关系,但Caretaker角色Memento角色之间是弱关联关系。Memento角色Caretaker角色隐藏了自身的内部信息

【划分Caretaker角色Originator角色的意义】

Caretaker角色的职责是决定何时拍摄快照,何时撤销以及保存Memento角色。另一方面,Originator 角色的职责则是生成Memento角色和使用接收到的Memento角色来恢复自己的状态。有了这样的职责分担,当我们需要应对以下的需求变更时,就不用修改Originator角色

  • 变更为可以多次撤销
  • 变更为不仅可以撤销,还可以将现在的状态保存在文件中

【Caretaker角色只能通过窄接口(API)来操作 Memento角色,如果Caretaker角色可以随意地操作Memento角色,会发生什么问题呢】

  • 破坏对象的封装性:Memento角色负责存储Originator角色的状态数据,如果Caretaker角色可以随意地操作Memento角色,那么就破坏了Memento对象和Originator对象的封装性
  • 不安全的状态恢复:如果Caretaker角色可以随意地操作Memento角色,可能会改变Memento对象中存储的状态数据,导致状态恢复产生错误
  • 无法保证数据的完整性:如果Caretaker角色可以随意地操作Memento角色,可能会在不正确的时间点保存状态数据,导致数据的不完整性

案例实现

案例一(基础案例)

类图

在这里插入图片描述

  • Originator:需要被保存状态的对象
  • Memento:备忘录对象,负责记录Originator对象的状态
  • Caretaker:守护者对象,负责保存多个备忘录对象,一般使用集合进行管理,提高管理效率

实现

【Originator】

package com.atguigu.memento.theory;public class Originator {/*** 角色的状态信息*/private String state;public String getState() {return state;}public void setState(String state) {this.state = state;}/*** 编写一个方法,可以保存一个状态对象 Memento* 因此编写一个方法,返回 Memento** @return*/public Memento saveStateMemento() {return new Memento(state);}/*** 通过备忘录对象获取原有状态信息,恢复状态** @param memento*/public void getStateFromMemento(Memento memento) {state = memento.getState();}
}

【Memento】

package com.atguigu.memento.theory;public class Memento {/*** 用来保存状态信息*/private String state;/*** 构造器** @param state*/public Memento(String state) {super();this.state = state;}/*** 获取保存的状态信息* @return*/public String getState() {return state;}}

【Caretaker】

package com.atguigu.memento.theory;import java.util.ArrayList;
import java.util.List;/*** 统一管理备忘录对象*/
public class Caretaker {/*** 在 List 集合中会有很多的备忘录对象* 如果想要保存多个Originator的多个状态,可以使用HashMap<Originator的ID,List<Memento>>*/private List<Memento> mementoList = new ArrayList<Memento>();public void add(Memento memento) {mementoList.add(memento);}/*** 获取 Originator 的 第 index 个 备忘录对象(即所保存的状态)** @param index* @return*/public Memento get(int index) {return mementoList.get(index);}
}

【主类】

package com.atguigu.memento.theory;public class Client {public static void main(String[] args) {Originator originator = new Originator();// 备忘录对象管理器Caretaker caretaker = new Caretaker();originator.setState(" 状态#1 攻击力 100 ");//保存了当前的状态caretaker.add(originator.saveStateMemento());originator.setState(" 状态#2 攻击力 80 ");caretaker.add(originator.saveStateMemento());originator.setState(" 状态#3 攻击力 50 ");caretaker.add(originator.saveStateMemento());System.out.println("当前的状态是 =" + originator.getState());//希望得到状态 1, 将 originator 恢复到状态1originator.getStateFromMemento(caretaker.get(0));System.out.println("恢复到状态1 , 当前的状态是 =" + originator.getState());}}

【运行】

当前的状态是 = 状态#3 攻击力 50 
恢复到状态1 , 当前的状态是 = 状态#1 攻击力 100 Process finished with exit code 0

案例二

类图

在这里插入图片描述

实现

【Originator:GameRole】

package com.atguigu.memento.game;public class GameRole {private int vit;private int def;/*** 创建Memento,即根据当前的状态得到Memento** @return*/public Memento createMemento() {return new Memento(vit, def);}/*** 从备忘录对象,恢复GameRole的状态** @param memento*/public void recoverGameRoleFromMemento(Memento memento) {this.vit = memento.getVit();this.def = memento.getDef();}/*** 显示当前游戏角色的状态*/public void display() {System.out.println("游戏角色当前的攻击力:" + this.vit + " 防御力: " + this.def);}public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}}

【Memento】

package com.atguigu.memento.game;public class Memento {/*** 攻击力*/private int vit;/*** 防御力*/private int def;public Memento(int vit, int def) {this.vit = vit;this.def = def;}public int getVit() {return vit;}public void setVit(int vit) {this.vit = vit;}public int getDef() {return def;}public void setDef(int def) {this.def = def;}}

【Caretaker】

package com.atguigu.memento.game;/*** 守护者对象, 保存游戏角色的状态*/
public class Caretaker {/*** 因为大战Boss之前只有一个状态,所以这里保存一次状态,不需要使用集合*/private Memento memento;//对GameRole保存多次状态//private ArrayList<Memento> mementos;//对多个GameRole保存多个状态//private HashMap<String, ArrayList<Memento>> rolesMementos;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}

【主类】

package com.atguigu.memento.game;public class Client {public static void main(String[] args) {//创建游戏角色GameRole gameRole = new GameRole();gameRole.setVit(100);gameRole.setDef(100);System.out.println("和boss大战前的状态");gameRole.display();//把当前状态保存caretakerCaretaker caretaker = new Caretaker();caretaker.setMemento(gameRole.createMemento());System.out.println("和boss大战~~~");gameRole.setDef(30);gameRole.setVit(30);gameRole.display();System.out.println("大战后,使用备忘录对象恢复到站前");gameRole.recoverGameRoleFromMemento(caretaker.getMemento());System.out.println("恢复后的状态");gameRole.display();}}

【运行】

和boss大战前的状态
游戏角色当前的攻击力:100 防御力: 100
和boss大战~~~
游戏角色当前的攻击力:30 防御力: 30
大战后,使用备忘录对象恢复到站前
恢复后的状态
游戏角色当前的攻击力:100 防御力: 100Process finished with exit code 0

案例三

案例说明

  • 游戏是自动进行的
  • 游戏的主人公通过掷骰子来决定下一个状态
  • 当骰子点数为1的时候,主人公的金钱会增加
  • 当骰子点数为2的时候,主人公的金钱会减少
  • 当骰子点数为6的时候,主人公会得到水果
  • 主人公没有钱时游戏就会结束

类图

在这里插入图片描述

实现

【Originator:Gamer】

package com.atguigu.memento.Sample.game;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;public class Gamer {/*** 所持金钱*/private int money;/*** 获得的水果*/private List fruits = new ArrayList();/*** 随机数生成器*/private Random random = new Random();/*** 表示水果种类的数组*/private static String[] fruitsName = {"苹果", "葡萄", "香蕉", "橘子",};/*** 构造函数** @param money*/public Gamer(int money) {this.money = money;}/*** 获取当前所持金钱** @return*/public int getMoney() {return money;}/*** 投掷骰子进行游戏*/public void bet() {// 掷骰子,随机获取一个点数int dice = random.nextInt(6) + 1;if (dice == 1) {//  骰子结果为1…增加所持金钱money += 100;System.out.println("所持金钱增加了。");} else if (dice == 2) {// 骰子结果为2…所持金钱减半money /= 2;System.out.println("所持金钱减半了。");} else if (dice == 6) {// 骰子结果为6…获得水果String f = getFruit();System.out.println("获得了水果(" + f + ")。");fruits.add(f);} else {// 骰子结果为3、4、5则什么都不会发生System.out.println("什么都没有发生。");}}/*** 拍摄快照** @return*/public Memento createMemento() {Memento m = new Memento(money);Iterator it = fruits.iterator();while (it.hasNext()) {String f = (String) it.next();if (f.startsWith("好吃的")) {// 只保存好吃的水果m.addFruit(f);}}return m;}/*** 撤销到指定状态** @param memento*/public void restoreMemento(Memento memento) {this.money = memento.money;this.fruits = memento.getFruits();}/*** 用字符串输出主人公的状态** @return*/public String toString() {return "[money = " + money + ", fruits = " + fruits + "]";}/*** 随机获取一个水果** @return*/private String getFruit() {String prefix = "";if (random.nextBoolean()) {prefix = "好吃的";}return prefix + fruitsName[random.nextInt(fruitsName.length)];}
}

【Memento】

package com.atguigu.memento.Sample.game;import java.util.ArrayList;
import java.util.List;public class Memento {/*** 游戏主人公所持金钱*/int money;/*** 游戏主人公当前获得的水果*/ArrayList fruits;/*** 获取当前所持金钱(narrow interface)* narrow interface:Memento角色为外部的 Caretaker 角色提供了“窄接口(API)”。可以通过窄接口(API)获取的Memento角色的内部信息非常有限,因此可以有效地防止信息泄露* @return*/public int getMoney() {return money;}/*** 构造函数(wide interface),只有相同包的Gamer类才使用该构造方法,因为方法修饰类型是default** @param money*/Memento(int money) {this.money = money;this.fruits = new ArrayList();}/*** 添加水果(wide interface)** @param fruit*/void addFruit(String fruit) {fruits.add(fruit);}/*** 获取当前所持所有水果(wide interface)* wide interface:“宽接口(API)”是指所有用于获取恢复对象状态信息的方法的集合。由于宽接口(API)会暴露所有Memento角色的内部信息,因此能够使用宽接口(API)的只有Originator 角色* @return*/List getFruits() {return (List) fruits.clone();}
}

【Caretaker】

package com.atguigu.memento.Sample;import com.atguigu.memento.Sample.game.Gamer;
import com.atguigu.memento.Sample.game.Memento;public class Main {public static void main(String[] args) {// 最初的所持金钱数为100Gamer gamer = new Gamer(100);// 保存最初的状态Memento memento = gamer.createMemento();for (int i = 0; i < 10; i++) {// 显示掷骰子的次数System.out.println("==== " + i);// 显示主人公现在的状态System.out.println("当前状态:" + gamer);// 进行游戏gamer.bet();System.out.println("所持金钱为" + gamer.getMoney() + "元。");// 决定如何处理Mementoif (gamer.getMoney() > memento.getMoney()) {System.out.println("    (所持金钱增加了许多,因此保存游戏当前的状态)");memento = gamer.createMemento();} else if (gamer.getMoney() < memento.getMoney() / 2) {System.out.println("    (所持金钱减少了许多,因此将游戏恢复至以前的状态)");gamer.restoreMemento(memento);}// 等待一段时间try {Thread.sleep(1000);} catch (InterruptedException e) {}System.out.println("");}}
}

【运行】

==== 0
当前状态:[money = 100, fruits = []]
什么都没有发生。
所持金钱为100元。==== 1
当前状态:[money = 100, fruits = []]
所持金钱增加了。
所持金钱为200元。(所持金钱增加了许多,因此保存游戏当前的状态)==== 2
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 3
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 4
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 5
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 6
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 7
当前状态:[money = 200, fruits = []]
什么都没有发生。
所持金钱为200元。==== 8
当前状态:[money = 200, fruits = []]
所持金钱减半了。
所持金钱为100元。==== 9
当前状态:[money = 100, fruits = []]
所持金钱增加了。
所持金钱为200元。Process finished with exit code 0

拓展

使用序列化(Serialization)功能来将Memento类的实例保存为文件。请修改示例程序以实现下列功能。

  • 在应用程序启动时,如果发现不存在game.dat文件时,以所持金钱数目为100开始游戏;如果发现 game.dat 已经存在,则以文件中所保存的状态开始游戏
  • 当所持金钱大量增加后,将Memento类的实例保存到game.dat文件中
  1. 将Memento继承Serializable接口来实现序列化操作,除此之外,不需要进行其他修改
public class Memento implements Serializable {}
  1. 想要扩展实例保存到文件的功能,只需要修改Caretaker
package com.atguigu.memento.A4;import com.atguigu.memento.A4.game.Gamer;
import com.atguigu.memento.A4.game.Memento;import java.io.*;public class Main {/*** 数据保存的文件名*/public static final String SAVE_FILE_NAME = "game.dat";public static void main(String[] args) {// 最初的所持金钱数为100Gamer gamer = new Gamer(100);// 从文件中读取起始状态Memento memento = loadMemento();if (memento != null) {System.out.println("读取上次保存存档开始游戏。");gamer.restoreMemento(memento);} else {System.out.println("新游戏。");memento = gamer.createMemento();}for (int i = 0; i < 100; i++) {// 显示次数System.out.println("==== " + i);// 显示当前主人公的状态System.out.println("当前状态:" + gamer);// 进行游戏gamer.bet();   System.out.println("所持金钱为" + gamer.getMoney() + "元。");// 决定如何处理Mementoif (gamer.getMoney() > memento.getMoney()) {System.out.println("    (所持金钱增加了许多,因此保存游戏当前的状态)");memento = gamer.createMemento();// 将实例保存至文件中saveMemento(memento);} else if (gamer.getMoney() < memento.getMoney() / 2) {System.out.println("    (所持金钱减少了许多,因此将游戏恢复至以前的状态)");gamer.restoreMemento(memento);}// 等待一段时间try {Thread.sleep(1000);} catch (InterruptedException e) {}System.out.println("");}}/*** 保存实例到文件中* @param memento*/public static void saveMemento(Memento memento) {   try {ObjectOutput out = new ObjectOutputStream(new FileOutputStream(SAVE_FILE_NAME));out.writeObject(memento);out.close();} catch (IOException e) {e.printStackTrace();}}/*** 从文件中读取实例* @return*/public static Memento loadMemento() {               Memento memento = null;try {ObjectInput in = new ObjectInputStream(new FileInputStream(SAVE_FILE_NAME));memento = (Memento)in.readObject();in.close();} catch (FileNotFoundException e) {System.out.println(e.toString());} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return memento;}
}

总结

【优点】

  • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回退到某个历史的状态
  • 实现了信息的封装,使用户不需要关心状态的保存细节

【缺点】

  • 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存,这个需要注意。为了节约内存,备忘录模式可以和原型模式配合使用

【适用应用场景】

  • 打游戏时的存档
  • Windows 里的ctrl+z
  • IE 中的后退
  • 数据库的事务管理

文章说明

  • 本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。
  • 本人还同步阅读《图解设计模式》书籍(图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社,2017.1),进而综合两者的内容,让知识点更加全面

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

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

相关文章

vuejs 设计与实现 - 渲染器的设计

渲染器与响应式系统的结合 本节&#xff0c;我们暂时将渲染器限定在 DOM 平台。既然渲染器用来渲染真实 DOM 元素&#xff0c;那么严格来说&#xff0c;下面的函数就是一个合格的渲染器: // 渲染器&#xff1a; function renderer(domString, container) {container.innerHTM…

用js快速生成一个简单的css原子库 例如: .mr-18 .pl-18

第三方css原子库的缺点 比如 tailwindcss&#xff0c;有学习成本最开始写的时候效率可能还没有我们自己手写效率高&#xff0c;需要配置&#xff0c;会有原始样式被覆盖的问题&#xff1b;总之就是一个字重 自己搓的优点 学习成本低灵活不会有副作用 <!DOCTYPE html>…

Linux 终端操作命令(2)内部命令

Linux 终端操作命令 也称Shell命令&#xff0c;是用户与操作系统内核进行交互的命令解释器&#xff0c;它接收用户输入的命令并将其传递给操作系统进行执行&#xff0c;可分为内部命令和外部命令。内部命令是Shell程序的一部分&#xff0c;而外部命令是独立于Shell的可执行程序…

Kafka API与SpringBoot调用

文章目录 首先需要命令行创建一个名为cities的主题&#xff0c;并且创建该主题的订阅者。 1、使用Kafka原生API1.1、创建spring工程1.2、创建发布者1.3、对生产者的优化1.4、批量发送消息1.5、创建消费者组1.6 消费者同步手动提交1.7、消费者异步手动提交1.8、消费者同异步手动…

Qt与电脑管家2

1.竖线的添加与样式的修改&#xff1a; color: rgb(238, 238, 238); 2. 通过修改之前的自定义btn类代码&#xff0c;可以比较容易地创造出各种各样的按钮类 头像的样式表代码&#xff1a; QPushButton{ border-image: url(:/images_up/icon.jpg); border-radius:20px; } QPu…

Expo项目 使用Native base UI库

装包&#xff1a; yarn add native-base expo install react-native-svg12.1.1 Index.js: import React from react import { View, Text } from react-native import useList from ./useList import { NativeBaseProvider, Button, Box } from native-base import styles f…

ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合)

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…

Spannable配合AnimationDrawable实现TextView中展示Gif图片

辣的原理解释&#xff0c;反正大家也不爱看&#xff0c;所以直接上代码了 长这样&#xff0c;下面两个图是gif&#xff0c;会动的。 package com.example.myapplication;import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable…

[静态时序分析简明教程(九)]多周期路径set_multicycle_path

静态时序分析简明教程-多周期路径 一、写在前面1.1 快速导航链接 二、多周期路径2.1 多周期路径的SDC命令2.2 路径常规约束2.3 建立/保持规格2.4 位移量2.5 多时钟周期案例 三、总结 一、写在前面 一个数字芯片工程师的核心竞争力是什么&#xff1f;不同的工程师可能给出不同的…

山景DSP芯片可烧录AP8224C2音频处理器方案

AP8224C2高性能32位音频应用处理器AP82系列音频处理器是面向音频应用领域设计的新一代SoC平台产品&#xff0c;适用于传统音响系统、新兴的蓝牙或Wifi 无线音频产品、Sound Bar 和调音台等市场。该处理器在总体架构和系统组成上&#xff0c;充分考虑了音频领域的特点&#xff0…

MYSQL幻读问题

幻读是什么&#xff1f; “Phantom Problem是指在同一事务下&#xff0c;连续执行两次同样的SQL语句可能导致不同的结果&#xff0c;第二次的SQL语句可能会返回之前不存在的行。”摘录来自 MySQL技术内幕&#xff1a;InnoDB存储引擎(第2版) (数据库技术丛书) ​ 通俗来说就是&a…

【积水成渊】9 个CSS 伪元素

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人_python人工智能视觉&#xff08;opencv&#xff09;从入门到实战,前端,微信小程序-CSDN博客 最新的uniapp毕业设计专栏也放在下方了&#xff1a; https://blog.csdn.net/lbcy…

Jupyter Notebook 500 : Internal Server Error

1. 这个问题的根本原因在于&#xff1a; pygments 包 版本过高。 安装pygments 2.6.1 2.jupyter版本如下 如果某个版本有冲突&#xff0c;卸载了重新安装一下就行。 安装命令&#xff1a; pip install pygments 2.6.1 -i https://pypi.tuna.tsinghua.edu.cn/simple 另外…

界面控件DevExpress WPF Chart组件——拥有超快的数据可视化库!

DevExpress WPF Chart组件拥有超大的可视化数据集&#xff0c;并提供交互式仪表板与高性能WPF图表库。DevExpress Charts提供了全面的2D / 3D图形集合&#xff0c;包括数十个UI定制和数据分析/数据挖掘选项。 PS&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助…

Mysql中插入数据,并返回自增主键的值

创建数据库和表使用 insert into 进行插入数据使用 RETURN_GENERATED_KEYS 进行返回插入的这条数据 具体方法如下&#xff1a; Testvoid addGetPk(){try{Statement stmt conn.createStatement();String sql String.format("insert into t_students values(null,%s,%s,%d…

「已解决」iframe 本地生效 但是在测试环境不生效问题

背景 我有一个表格中一列是个详情&#xff0c;这个详情可被点击&#xff0c;点击后弹出抽屉&#xff0c;抽屉里是后端传给我详情字段的值对应的 url 的 iframe 展示。 问题是&#xff0c;在本地 localhost 下运行&#xff0c;ifame 运行正常&#xff0c;但是部署到测试环境就看…

王道机组难题分析

第四章 指令系统 大端方式&#xff1a;就是高地址存放高位&#xff0c; LSB的意思是&#xff1a;全称为Least Significant Bit&#xff0c;在二进制数中意为最低有效位 MSB的意思是&#xff1a;全称为Most Significant Bit&#xff0c;在二进制数中属于最高有效位 操作数可以理…

JavaWeb-Servlet服务连接器(三)

目录 Response响应对象 1.基本功能 2.重定向 3.路径 4.服务器输出数据到浏览器 Response响应对象 1.基本功能 设置响应行&#xff1a;格式为 HTTP/1.1 200 OK&#xff0c;可以使用 setStatus(int sc) 方法设置状态码为 200 表示成功。 方法名称描述setStatus(int sc)设…

docker下载和案例

文章目录 Docker安装一,根据官方文档安装二,根据我以下方式 Docker配置错误导致漏洞一,CRLF注入漏洞介绍在nginx中该漏洞例子解决方法 目录穿越漏洞介绍解决方法 Docker安装 一,根据官方文档安装 官方文档 二,根据我以下方式 docker安装要求&#xff1a; Docker要求Ce…

用户数据报协议UDP

UDP的格式 载荷存放的是:应用层完整的UDP数据报 报头结构: 源端口号:发出的信息的来源端口目的端口号:信息要到达的目的端口UDP长度:2个字节(16位),即UDP总长度为:2^16bit 2^10bit * 2^6bit 1KB * 64 64KB.所以一个UDP的最大长度为64KBUDP校验和:网络的传输并非稳定传输,…