设计模式之备忘录模式笔记

news2024/11/23 9:19:27

设计模式之备忘录模式笔记

  • 说明
  • Memento(备忘录)
  • 目录
  • 白箱备忘录模式
    • 备忘录模式示例类图
    • 游戏角色类
    • 备忘录角色类
    • 备忘录对象管理对象
    • 测试类
  • 黑箱备忘录模式
    • 备忘录模式示例类图
    • 备忘录接口
    • 游戏角色类
    • 备忘录对象管理对象
    • 测试类

说明

记录下学习设计模式-备忘录模式的写法。JDK使用版本为1.8版本。

Memento(备忘录)

意图:在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态。
结构:
在这里插入图片描述

其中:

  • Memento(备忘录)存储原发器对象的内部状态,原发器根据需要决定备忘录存储原发器的哪些内部状态:防止原发器以外的其他对象访问备忘录。
  • Originator(原发器)创建一个备忘录,用于记录当前时刻它的内部状态;使用备忘录恢复内部状态。
  • Caretaker(管理者)负责保存好备忘录;不能对备忘录的内容进行操作或检查。

适用性:

  • 需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
  • 需要提供一个可回滚操作的场景,如 word记事本、Photoshop,idea等软件在编辑时按 Ctrl+ 组合键,还有数据库中事务操作。

目录

在这里插入图片描述

白箱备忘录模式

备忘录模式示例类图

在这里插入图片描述
在这里插入图片描述

以该UML类图实现白箱备忘录模式示例。

游戏角色类

package com.example.deesign_patterns.memento.white_box;

//游戏角色类(属于发起人角色)
public class GameRole {

    private int vit;//生命力
    private int atk;//攻击力
    private int def;//防御力

    //初始化内部状态
    public void initState(){
        this.vit=100;
        this.atk=100;
        this.def=100;
    }

    //战斗方法
    public void fight(){
        this.vit=0;
        this.atk=0;
        this.def=0;
    }

    //保存角色状态功能
    public RoleStateMemento saveState(){
        return new RoleStateMemento(vit,atk,def);
    }

    //恢复角色状态
    public void recoverState(RoleStateMemento roleStateMemento){
        //将备忘录对象中存储的状态赋值给当前对象的成员
        this.vit=roleStateMemento.getVit();
        this.atk=roleStateMemento.getAtk();
        this.def=roleStateMemento.getDef();
    }

    //展示状态功能
    public void stateDisplay(){
        System.out.println("角色生命力:"+vit);
        System.out.println("角色攻击力:"+atk);
        System.out.println("角色防御力:"+def);
    }

    public int getVit() {
        return vit;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getDef() {
        return def;
    }

    public void setDef(int def) {
        this.def = def;
    }
}

备忘录角色类

package com.example.deesign_patterns.memento.white_box;

//备忘录角色类
public class RoleStateMemento {

    private int vit;//生命力
    private int atk;//攻击力
    private int def;//防御力

    public RoleStateMemento() {
    }

    public RoleStateMemento(int vit, int atk, int def) {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }

    public int getVit() {
        return vit;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getDef() {
        return def;
    }

    public void setDef(int def) {
        this.def = def;
    }
}

备忘录对象管理对象

package com.example.deesign_patterns.memento.white_box;

//备忘录对象管理对象
public class RoleStateCaretaker {

    //声明RoleStateMemento类型的变量
    private RoleStateMemento roleStateMemento;

    public RoleStateMemento getRoleStateMemento() {
        return roleStateMemento;
    }

    public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
        this.roleStateMemento = roleStateMemento;
    }
}

测试类

package com.example.deesign_patterns.memento.white_box;

//测试类
public class Client {

    public static void main(String[] args) {
        System.out.println("-----------大战boos前-------------");
        //创建游戏角色对象
        GameRole gameRole=new GameRole();
        gameRole.initState();
        gameRole.stateDisplay();
        //将该游戏角色内部状态进行备份
        //创建管理者对象
        RoleStateCaretaker roleStateCaretaker=new RoleStateCaretaker();
        roleStateCaretaker.setRoleStateMemento(gameRole.saveState());

        System.out.println("-----------大战boos后-------------");
        //损耗严重
        gameRole.fight();
        gameRole.stateDisplay();

        System.out.println("-----------恢复之前的状态-------------");
        gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
        gameRole.stateDisplay();
    }
}

在这里插入图片描述

黑箱备忘录模式

备忘录模式示例类图

备忘录角色对发起人对象提供一个宽接口,而为其他对象提供一个窄接口。在Java语言中,实现双重接口的办法就是将备忘录类设计成发起人类的内部成员类。

将 RolestateMemento 设为 GameRole 的内部类,从而将 RoleStateMemento 对象封装在 Gamerole 里面:在外面提供-个标识接口 Memento 给 Rolestatecaretaker 及其对象使用。这样Gamerole 类看到的是 RoleStateMemento 所有的接口,而及其他对象看到的仅仅是标识接口 Memento 所暴露出来的接口,从而维护了封装型。类图如下:
在这里插入图片描述

以该UML类图实现黑箱备忘录模式示例。

备忘录接口

package com.example.deesign_patterns.memento.black_box;

//备忘录接口,对外提供窄接口
public interface Memento {
}

游戏角色类

package com.example.deesign_patterns.memento.black_box;

//游戏角色类(属于发起人角色)
public class GameRole {

    private int vit;//生命力
    private int atk;//攻击力
    private int def;//防御力

    //初始化内部状态
    public void initState(){
        this.vit=100;
        this.atk=100;
        this.def=100;
    }

    //战斗方法
    public void fight(){
        this.vit=0;
        this.atk=0;
        this.def=0;
    }

    //保存角色状态功能
    public Memento saveState(){
        return new RoleStateMemento(vit,atk,def);
    }

    //恢复角色状态
    public void recoverState(Memento memento){
        RoleStateMemento roleStateMemento= (RoleStateMemento) memento;
        //将备忘录对象中存储的状态赋值给当前对象的成员
        this.vit=roleStateMemento.getVit();
        this.atk=roleStateMemento.getAtk();
        this.def=roleStateMemento.getDef();
    }

    //展示状态功能
    public void stateDisplay(){
        System.out.println("角色生命力:"+vit);
        System.out.println("角色攻击力:"+atk);
        System.out.println("角色防御力:"+def);
    }

    public int getVit() {
        return vit;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public int getAtk() {
        return atk;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public int getDef() {
        return def;
    }

    public void setDef(int def) {
        this.def = def;
    }

    //声明一个内部类
    private class RoleStateMemento implements Memento{
        private int vit;//生命力
        private int atk;//攻击力
        private int def;//防御力

        public RoleStateMemento() {
        }

        public RoleStateMemento(int vit, int atk, int def) {
            this.vit = vit;
            this.atk = atk;
            this.def = def;
        }

        public int getVit() {
            return vit;
        }

        public void setVit(int vit) {
            this.vit = vit;
        }

        public int getAtk() {
            return atk;
        }

        public void setAtk(int atk) {
            this.atk = atk;
        }

        public int getDef() {
            return def;
        }

        public void setDef(int def) {
            this.def = def;
        }
    }
}

备忘录对象管理对象

package com.example.deesign_patterns.memento.black_box;


//备忘录对象管理对象
public class RoleStateCaretaker {

    //声明Memento类型的变量
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

测试类

package com.example.deesign_patterns.memento.black_box;

//测试类
public class Client {

    public static void main(String[] args) {
        System.out.println("-----------大战boos前-------------");
        //创建游戏角色对象
        GameRole gameRole=new GameRole();
        gameRole.initState();
        gameRole.stateDisplay();
        //将该游戏角色内部状态进行备份
        //创建管理者对象
        RoleStateCaretaker roleStateCaretaker=new RoleStateCaretaker();
        roleStateCaretaker.setMemento(gameRole.saveState());

        System.out.println("-----------大战boos后-------------");
        //损耗严重
        gameRole.fight();
        gameRole.stateDisplay();

        System.out.println("-----------恢复之前的状态-------------");
        gameRole.recoverState(roleStateCaretaker.getMemento());
        gameRole.stateDisplay();
    }
}

在这里插入图片描述

好处:

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

缺点:

  • 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

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

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

相关文章

JDBC小记——连接池

目录 连接池介绍 常用连接池 DBCP连接池 硬编码方式 配置文件方式 C3P0连接池 C3P0和DBCP的区别 硬编码方式 配置文件方式 Druid连接池 硬编码方式 配置文件方式 DBUtils 连接池介绍 由于建立数据库连接是一种非常耗时、耗资源的行为,所以预先通过连接…

在vite+vue3项目中配置使用css预处理器(less/sass)以及路径别名

一、在vite项目中使用css预处理器 vite已经将这些预处理器的loader内置了,我们不用再像在webpack项目中那样,需要下载和配置一堆相关的loader,我们只需要下载less,sass依赖,就能直接在项目中使用啦 使用npm或者yarn来…

Springboot-- 注解字段校验,并统一设置返回值

Springboot-- 注解字段校验&#xff0c;并统一设置返回值 引包&#xff1a;import org.springframework.validation.annotation.Validated; <!--web--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

配置鼠标右键菜单功能 :一键csv转excel

配置右键菜单功能 &#xff1a;一键csv转excel 无需点开文件&#xff0c;双击即可以生成新的excel文件 步骤&#xff1a; 1、配置Python&#xff0c;安装依赖库 pip install openpyxl pip install pandas2、创建Python文件 csv_to_excel.py # -*- coding:utf-8 -*- impor…

【计算机组成原理】函数栈帧

目录 一、源代码理论分析 二、主函数的创建 三、c语言代码的汇编 注&#xff1a;不同编译器环境的函数栈帧存在一定差异&#xff0c;本文使用VS2019 一、源代码理论分析 源代码&#xff1a; int Add(int x, int y) {int z 0;z x y;return z; }int main() {int a 10;…

u盘安装centos 7

1.下载 通过阿里云站点&#xff1a;http://mirrors.aliyun.com/centos/7/isos/x86_64/&#xff0c;下载iso文件。 2.制作启动u盘镜像 2.1 下载制作工具 下载u启动 http://uqidong.als98.cn/ 。 2.2 制作镜像 准备u盘&#xff0c;插入机器&#xff0c;运行u启动。 注意…

机器学习之基于PCA的人脸识别

目录 PCA人脸数据降维 matlab代码实现 思路分析 PCA人脸重构 matlab代码实现 思路分析 PCA人脸可视化 matlab代码实现 思路分析&#xff1a; PCA人脸识别 matlab代码实现 思路分析 PCA人脸数据降维 matlab代码实现 picturesdir(C:\Users\Yezi\Desktop\机…

数字逻辑与模拟电子技术-部分知识点(2)——模电部分-半导体三极管、基本线性运放电路、正弦波振荡电路

目录 半导体三极管 三极管的放大的条件 基本放大电路计算 基本线性运放电路 同相放大电路 反相放大电路 加法器放大电路 正弦波振荡电路 正弦波振荡的条件 半导体三极管 三极管的放大的条件 主要是依靠它的发射极电流能够通过基区传输&#xff0c;然后到达集电极而实现…

【KMP算法】时间复杂度O(N)的字符串匹配算法

目录 案例&#xff1a;假定我们给出字符串 ”ababcabcdabcde”作为主串&#xff0c; 然后给出子串&#xff1a; ”abcd”,现在我们需要查找子串是否在主串中 出现&#xff0c;出现返回主串中的第一个匹配的下标&#xff0c;失败返回-1 ; 1.BF算法&#xff08;暴力算法&#x…

java8新特性之--强大的Stream API详细讲解

强大的Stream API Stream API说明 Java8中有两大最为重要的改变。第一个是 Lambda 表达式&#xff1b;另外一个则 是 Stream API。Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。 这是目前为止对Java类库最好的补充&#xff0c;因为Stream API可以极…

CVPR 23 | 高分辨率缺陷异常定位新范式:PyramidFlow

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2303.02595 论文代码&#xff1a;暂未发布 0. 背景 由于复杂的工业制造过程中的不可控因素&#xff0c;不可避免地会给产品带来不可预见的缺陷。由于人类视觉系…

使用亮数据Bright Data解决出境电商问题

目录 一、出境电商的困境和问题1、困境一&#xff1a;获取准确的市场数据&#xff08;1&#xff09;数据的时效性和可靠性&#xff08;2&#xff09;数据的全面性和多样性&#xff08;3&#xff09;数据的实时更新和持续监测 2、困境二&#xff1a;克服地域限制和语言障碍&…

scratch数星星 2023年5月中国电子学会图形化编程 少儿编程 scratch编程等级考试三级真题和答案解析

目录 scratch数星星 一、题目要求 1、准备工作 2、功能实现 二、案例分析

基于Java学生信息管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

vue中js实现点击复制文本到剪贴板-三种方案

vue中js实现点击复制文本到剪贴板-三种方案 因为在网上找了一些很杂乱 不适用 所以自己写一篇记录分享一下 vue中js实现点击复制文本到剪贴板-三种方案 效果&#xff1a; 方案一&#xff1a;使用原生API&#xff08;clipboard&#xff09; 首先&#xff0c;我们需要安装clip…

【嵌入式5】电源相关芯片驱动

文章目录 1.读MPS5023芯片&#xff1a;0x03ff即将前6位屏蔽2.读PXE1410CDM电压和电流&#xff1a;一个数&0x7ff&#xff0c;将这个数前5位全变为0&#xff0c;其余位不变2.1 1ine11&#xff1a;先看第15和10位&#xff0c;e9b6是上面读出的值2.2 1ine16&#xff1a;PMBUS协…

产品的0到1概念篇

一、产品是什么&#xff1f; 产品是指被人们使用和消费&#xff0c;并能满足人们某种需求的任何东西&#xff0c;包括有形的物品、无形的服务、组织、观念或它们的组合。 产品本质是什么&#xff0c;产品的本质就是解决⽤户的痛点/满⾜⽤户的需求&#xff0c;这种满⾜的需求&…

KingbaseES的学习心得和知识总结(二)|Kingbase数据库闪回功能及插件kdb_flashback的使用

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、KingbaseES V8产品文档首页&#xff0c;点击前往 2、Kingbase 文档库&#xff0c;点击前往 3、北京人大金仓信息技术股份有限公司 官网首页&#xff0c;点击前往…

详解服务器端渲染 页面(SSR)

&#x1f48c;目录 &#x1f525;先了解服务器端渲染 (SSR)&#xff1f;&#x1f525;服务器端渲染的优点是什么呢&#xff1f;&#x1f525;有优点就有缺点&#xff1f;&#x1f525;根据Express来简单的建立一个服务端渲染 &#x1f525;先了解服务器端渲染 (SSR)&#xff1f…

Qt6.2教程——7.QT常用控件QTextEdit

一&#xff0c;QTextEdit简介 QTextEdit 是 Qt 的一个用于编辑和显示纯文本和富文本的控件。它是功能强大且高度灵活的&#xff0c;可以用于实现多种任务&#xff0c;如文本编辑&#xff0c;数据表示&#xff0c;以及HTML的显示和编辑等。QTextEdit 支持富文本功能&#xff0c…