Java设计模式-备忘录模式、备忘录模式应用场景是什么、又怎么使用

news2024/11/18 2:39:56

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用!

6.11 备忘录模式

6.11.1 定义

又称快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存此状态,以便后续需要时将该对象恢复到原先保存的状态

6.11.2 结构

  • 发起人角色(originator):记录当前时刻的内部状态信息,提供创备忘录和恢复备忘录数据的功能,实现其他业务功能,可以访问备忘录里的所有信息
  • 备忘录角色(memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人
  • 管理者角色(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录内容进行访问与修改
  • 两个等效接口:
    • 窄接口:管理对象(和发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow interface),此接口仅仅运行它把备忘录对象传给其他对象
    • 宽接口:发起人可以看到宽接口(wide interface),此接口运行它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态

6.11.3 案例

6.11.3.1 白箱模式

  • 特点:对所有对象提供一个宽接口,违反了封闭原则
  • 游戏角色
public class GameRole {  
//    角色名称  
    private String name;  
//    生命力  
    private int vita;  
//    攻击力  
    private int attack;  
//    防御力  
    private int defender;  
    public int getVita() {  
        return vita;  
    }  
    public void setVita(int vita) {  
        this.vita = vita;  
    }  
    public int getAttack() {  
        return attack;  
    }  
    public void setAttack(int attack) {  
        this.attack = attack;  
    }  
    public int getDefender() {  
        return defender;  
    }  
    public void setDefender(int defender) {  
        this.defender = defender;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    //    初始化状态  
    public void initState(){  
        this.attack = 100;  
        this.vita = 100;  
        this.defender = 100;  
    }  
//    战斗  
    public void fight(){  
        this.vita -= 50;  
        this.attack -= 50;  
        this.defender -= 50;  
    }  
//    保存状态  
    public RoleStateMemento saveState(){  
        return new RoleStateMemento(name,vita,attack,defender);  
    }  
//    恢复角色状态  
    public void recoverState(RoleStateMemento roleStateMemento){  
//        将备忘录对象中数据赋值给角色对象成员  
        this.vita = roleStateMemento.getVita();  
        this.attack = roleStateMemento.getAttack();  
        this.defender = roleStateMemento.getDefender();  
    }  
//    展示角色属性  
    public void display(){  
        System.out.println("角色" + name + "属性:");  
        System.out.println("角色生命力:" + this.vita);  
        System.out.println("角色攻击力:" + this.attack);  
        System.out.println("角色防御力:" + this.defender);  
    }  
}
  • 备忘录对象
public class RoleStateMemento {  
    //    角色名称  
    private String name;  
    //    生命力  
    private int vita;  
    //    攻击力  
    private int attack;  
    //    防御力  
    private int defender;  
    public int getVita() {  
        return vita;  
    }  
    public void setVita(int vita) {  
        this.vita = vita;  
    }  
    public int getAttack() {  
        return attack;  
    }  
    public void setAttack(int attack) {  
        this.attack = attack;  
    }  
    public int getDefender() {  
        return defender;  
    }  
    public void setDefender(int defender) {  
        this.defender = defender;  
    }  
    public String getName() {  
        return name;  
    }  
    public RoleStateMemento(String name, int vita, int attack, int defender) {  
        this.attack = attack;  
        this.vita = vita;  
        this.defender = defender;  
        this.name = name;  
    }  
    public RoleStateMemento() {  
    }  
}
  • 备忘录管理对象
public class RoleStateManage {  
//    用集合存储备忘录对象  
    private Map<String,RoleStateMemento> map = new HashMap<String,RoleStateMemento>();  
//    添加备忘录对象  
    public void addRoleStateMemento(RoleStateMemento roleStateMemento){  
        map.put(roleStateMemento.getName(),roleStateMemento);  
    }  
//    获取备忘录对象  
    public RoleStateMemento getRoleStateMemento(String name){  
        return map.get(name);  
    }  
}
  • 测试
    public static void main(String[] args) {  
        System.out.println("大战前-----------------------");  
//        创建角色  
        GameRole gameRole = new GameRole();  
        gameRole.setName("张三");  
//        初始化  
        gameRole.initState();  
//        展示  
        gameRole.display();  
//        保存状态  
        RoleStateMemento roleStateMemento = gameRole.saveState();  
        RoleStateManage roleStateManage = new RoleStateManage();  
        roleStateManage.addRoleStateMemento(roleStateMemento);  
        System.out.println("大战-----------------------");  
        gameRole.fight();  
//        展示  
        gameRole.display();  
        System.out.println("大战后-----------------------");  
//        恢复状态  
        roleStateMemento = roleStateManage.getRoleStateMemento("张三");  
        gameRole.recoverState(roleStateMemento);  
//        展示  
        gameRole.display();  
    }
  • 结果![[Pasted image 20230117212002.png]]

  • 类图![[Pasted image 20230117212119.png]]

6.11.4.1 黑箱模式

  • 改进:对发起任对象提供宽接口,为其它对象提供窄接口。具体是将备忘录对象设置为发起人的内部成员类
  • 抽象备忘录接口,供外部访问
public interface Memento {  
}
  • 游戏角色
public class GameRole {  
//    角色名称  
    private String name;  
//    生命力  
    private int vita;  
//    攻击力  
    private int attack;  
//    防御力  
    private int defender;  
    public int getVita() {  
        return vita;  
    }  
    public void setVita(int vita) {  
        this.vita = vita;  
    }  
    public int getAttack() {  
        return attack;  
    }  
    public void setAttack(int attack) {  
        this.attack = attack;  
    }  
    public int getDefender() {  
        return defender;  
    }  
    public void setDefender(int defender) {  
        this.defender = defender;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    //    初始化状态  
    public void initState(){  
        this.attack = 100;  
        this.vita = 100;  
        this.defender = 100;  
    }  
//    战斗  
    public void fight(){  
        this.vita -= 50;  
        this.attack -= 50;  
        this.defender -= 50;  
    }  
//    保存状态  
    public RoleStateMemento saveState(){  
        return new RoleStateMemento(vita,attack,defender);  
    }  
//    恢复角色状态  
    public void recoverState(Memento memento){  
        RoleStateMemento roleStateMemento = (RoleStateMemento) memento;  
//        将备忘录对象中数据赋值给角色对象成员  
        this.vita = roleStateMemento.getVita();  
        this.attack = roleStateMemento.getAttack();  
        this.defender = roleStateMemento.getDefender();  
    }  
//    展示角色属性  
    public void display(){  
        System.out.println("角色" + name + "属性:");  
        System.out.println("角色生命力:" + this.vita);  
        System.out.println("角色攻击力:" + this.attack);  
        System.out.println("角色防御力:" + this.defender);  
    }  
    //备忘录对象
    private class RoleStateMemento implements Memento {  
        //    生命力  
        private int vita;  
        //    攻击力  
        private int attack;  
        //    防御力  
        private int defender;  
        public int getVita() {  
            return vita;  
        }  
        public void setVita(int vita) {  
            this.vita = vita;  
        }  
        public int getAttack() {  
            return attack;  
        }  
        public void setAttack(int attack) {  
            this.attack = attack;  
        }  
        public int getDefender() {  
            return defender;  
        }  
        public void setDefender(int defender) {  
            this.defender = defender;  
        }  
        public RoleStateMemento(int vita, int attack, int defender) {  
            this.attack = attack;  
            this.vita = vita;  
            this.defender = defender;  
        }  
    }  
}
  • 管理备忘录对象
public class RoleStateManage {  
//    用集合存储备忘录对象  
    private Map<String, Memento> map = new HashMap<String, Memento>();  
//    添加备忘录对象  
    public void addRoleStateMemento(String name,Memento memento){  
        map.put(name,memento);  
    }  
//    获取备忘录对象  
    public Memento getRoleStateMemento(String name){  
        return map.get(name);  
    }  
}
  • 测试
    public static void main(String[] args) {  
        System.out.println("大战前-----------------------");  
//        创建角色  
        GameRole gameRole = new GameRole();  
        gameRole.setName("张三");  
//        初始化  
        gameRole.initState();  
//        展示  
        gameRole.display();  
//        保存状态  
        Memento roleStateMemento = gameRole.saveState();  
        RoleStateManage roleStateManage = new RoleStateManage();  
        roleStateManage.addRoleStateMemento("张三",roleStateMemento);  
        System.out.println("大战-----------------------");  
        gameRole.fight();  
//        展示  
        gameRole.display();  
        System.out.println("大战后-----------------------");  
//        恢复状态  
        Memento memento= roleStateManage.getRoleStateMemento("张三");  
        gameRole.recoverState(memento);  
//        展示  
        gameRole.display();  
    }
  • 结果不变,同上
  • 类图![[Pasted image 20230117214818.png]]

6.11.4 优缺点

6.11.4.1 优点

  • 提供了一种可以恢复状态的机制,当用户需要时能方便的将数据恢复到某个历史的状态
  • 实现了内部状态的封装,除了创建它的发起人外,其它对象都不能访问这些状态信息
  • 简化了发起人类,发起人不需要管理和保存其内部状态的备份,所有状态信息保存在备忘录,并有管理者进行管理,复合单一职责原则

6.11.4.2 缺点

  • 资源消耗大,若保存频繁或内部状态信息过多,会消耗内存

6.11.5 使用场景

  • 需要保存和恢复数据的场景,如游戏存档
  • 需要提供一个可回滚操作,如记事本,Word等

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

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

相关文章

深入学习Vue.js(十一)内建组件和模块

文章目录KeepAlive组件的实现原理1.KeepAlive组件实现原理2.KeepAlive组件的代码实现&#xff08;1&#xff09;shouldKeepAlive&#xff08;2&#xff09;keepAliveInstance&#xff08;3&#xff09;keptAlive&#xff08;4&#xff09;move函数3.include和exclude4.缓存策略…

视频生成动画数据OpenPose+OpenCV

我们只是使用OpenPose&#xff0c;不包括深度学习和代码的部分&#xff0c;会用就OK。 1.打开OpenPose的官网&#xff0c;直接进入安装页面&#xff0c;地址如下&#xff1a; OpenPose: OpenPose Doc - Installation 2.安装的说明&#xff0c;大家要好好看&#xff0c;我们就…

吴恩达机器学习课程笔记:多元梯度下降法

1.吴恩达机器学习课程笔记&#xff1a;多元梯度下降法 笔记来源&#xff1a;吴恩达机器学习课程笔记&#xff1a;多元梯度下降法 仅作为个人学习笔记&#xff0c;若各位大佬发现错误请指正 1.1 多元特征&#xff08;变量&#xff09; 每一列代表一个特征&#xff0c;例如&…

【Github CLI】Take GitHub to the command line

目录儿~一、Git、Github、GitLab二、Github CLI——gh2.1 gh简介2.2 gh的使用2.21 Github身份验证&#xff08;必选&#xff09;2.22 常用命令&#xff08;1&#xff09;在Github仓库中打开当前项目&#xff08;2&#xff09;gh配置 gh config&#xff08;3&#xff09;克隆仓库…

(16)go-micro微服务jaeger链路追踪

文章目录一 jaeger链路追踪介绍什么是链路追踪&#xff1a;链路追踪主要功能&#xff1a;二 jaeger链路追踪作用三 jaeger链路追踪主要特性四 jaeger链路追踪原理图1.链路调用原理2. 一次调用链分析3.链路追踪存储与调用五 jaeger链路追踪五个重要组件六 jaeger链路追踪安装1.d…

Junit框架

JUnit 是一个 Java 编程语言的单元测试框架。环境配置创建maven项目&#xff0c;导入Junit配置<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --> <dependency><groupId>org.junit.jupiter</groupId><artifactId&g…

Linux常用命令——tail命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) tail 在屏幕上显示指定文件的末尾若干行 补充说明 tail命令用于输入文件中的尾部内容。tail命令默认在屏幕上显示指定文件的末尾10行。如果给定的文件不止一个&#xff0c;则在显示的每个文件前面加一个文件名…

【docker概念和实践 4】 常见命令和案例(1)

一、说明 本篇讲述当Docker安装完成后&#xff0c;进行的由浅入深的操作过程。命令种类有&#xff1a;1 进程引擎进程命令 2帮助命令 3 镜像命令 4 容器命令 5 仓库命令。 二、关于操作引擎的指令 本节讲操作引擎的启动、关闭、维护等。以下两种形势都是等价的命令格式。 方法…

Java概览——Java运行机制

Java概览—Java运行机制Java的运行过程 Java程序运行时&#xff0c;必须经过编译和运行两个步骤。首先将后缀名为.java的源文件进行编译&#xff0c;最终生成后缀名为.class的字节码文件&#xff0c;然后Java虚拟机&#xff0c;将字节码文件进行解释执行&#xff0c;并将结果显…

Docker学习笔记【part1】概念与安装

一、Docker的概念 Docker 是实现系统平滑移植、容器虚拟化的技术&#xff0c;基于 Go语言&#xff0c;可以实现软件带环境安装&#xff0c;做到“一次镜像&#xff0c;处处运行”。Docker 是一个 C/S 模式的架构&#xff0c;后端是一个松耦合架构&#xff0c;众多模块各司其职…

九龙证券|次新股叠加智慧交通+信创+数字经济概念,开盘冲涨停!

核算机板块1月以来跑赢上证指数&#xff1b;才智交通、成绩高增及严重财物重组个股登上涨停榜。 证券时报•数据宝核算&#xff0c;1月19日&#xff0c;沪深两市收盘涨停股35只&#xff0c;其中ST股6只。群众交通、长久科技两股一字板强势涨停&#xff0c;潞安环能、跃岭股份收…

【MySQL】第五部分 多表查询

【MySQL】第五部分 多表查询 文章目录【MySQL】第五部分 多表查询5. 多表查询5.1 等值连接5.2 非等值连接5.3 自连接5.4 内连接5.5 外连接5.6 满外连接5.7 SQL99语法实现多表查询5.7.1 JOIN...ON语法5.7.2 使用SQL99语法实现内连接5.7.3 使用SQL99语法实现左外连接和右外连接5.…

postman入门

目录 新建界面 菜单区 百度翻译api实战 post 参数化 新建界面 1&#xff09;可以新建请求&#xff0c;&#xff08;rqueset&#xff09;模拟客户端的请求&#xff0c; 2&#xff09;可以创建测试集合&#xff08;collection&#xff09;&#xff0c;对接口请求进行统一管理…

删除排序链表中的重复元素

删除排序链表中的重复元素 题目描述 原始题目参考&#xff1a;删除有序链表的重复元素 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1…

java spring IOC Bean管理操作(xml P名称空间注入)

首先 我们来写一个基本的 通过xml的set属性注入 首先创建一个项目 然后引入 spring 最基本的几个依赖包 src下 下有一个 gettingStarted 包 下面有一个 user类 代码如下 package gettingStarted;public class user {public String name;public int age;public void setName(S…

leetcode 1817. 查找用户活跃分钟数【python3,哈希表的实现思路详解】

题目 给你用户在 LeetCode 的操作日志&#xff0c;和一个整数k。日志用一个二维整数数组logs表示&#xff0c;其中每个logs[i] [IDi, timei]表示ID为IDi的用户在timei分钟时执行了某个操作。 多个用户可以同时执行操作&#xff0c;单个用户可以在同一分钟内执行多个操作。指定…

Deno不只是个Javascript运行时

Deno 是一个安全的 JavaScript 和 TypeScript 运行时&#xff0c;作者是 Ryan Dahl&#xff08;也是 Node.js 的原作者&#xff09;。Deno 的诞生之初是为了解决 2009 年首次设计 Node.js 时的一些疏忽。我认为这种改造动机很有道理&#xff0c;因为我相信每个程序员都希望有机…

cmake跨平台构建工具

TOP目录 前言 CMake是一个跨平台的安装编译工具&#xff0c;可以用简单的语句来描述所有平台的安装(编译过程)。CMake可以说已经成为大部分C开源项目标配 因此&#xff0c;作为一名C C发开人员&#xff0c;看到cmake不应该一脸茫然… 作为初学者&#xff0c;通俗的认为cmake…

C语言入门(七)——结构体

复合类型与结构体 数据抽象 数据类型标志 嵌套结构体 复合类型与结构体 在编程语言中&#xff0c;最基本的&#xff0c;不可再分的数据类型称为基本类型&#xff0c;例如整型&#xff0c;浮点型;根据语法规则由基本类型组合而成的类型称为复合类型&#xff0c;例如字符串是…

系统性能优化、性能指标、性能测试

系统性能是互联网应用最核心的非功能性架构目标&#xff0c;系统因为高并发访问引起的首要问题就是性能问题&#xff1a;高并发访问的情况下&#xff0c;系统因为资源不足&#xff0c;处理每个请求的时间就会变慢&#xff0c;看起来就是性能变差。 因此&#xff0c;性能优化是…