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

news/2024/6/16 18:18:51 标签: 设计模式, 备忘录模式, java, 后端

设计模式备忘录模式笔记

说明

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

Memento(备忘录)

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

其中:

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

适用性:

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

目录

在这里插入图片描述

白箱备忘录模式

备忘录模式示例类图

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

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

游戏角色类

java">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;
    }
}

备忘录角色类

java">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;
    }
}

备忘录对象管理对象

java">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;
    }
}

测试类

java">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类图实现黑箱备忘录模式示例。

备忘录接口

java">package com.example.deesign_patterns.memento.black_box;

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

游戏角色类

java">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;
        }
    }
}

备忘录对象管理对象

java">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;
    }
}

测试类

java">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.niftyadmin.cn/n/467308.html

相关文章

开窗函数之聚合、取特定值、排名

一, 聚合开窗函数sum(score) over(partition by name ) 二,开窗函数之first_value,last_value,lead,lag 三,排名开窗函数ROW_NUMBER、DENSE_RANK、RANK 一,开窗函数的语法 开窗函数的语法为&am…

【kotlin笔记04】kotlin之单例模式、伴生对象、委托机制、异常处理、集合框架

这篇文章,主要介绍kotlin之单例模式、伴生对象、委托机制、异常处理、集合框架。 目录 一、kotlin笔记 1.1、kotlin单例模式 (1)单例类 (2)伴生对象 1.2、委

unity 性能优化学习笔记——静态资源的导入

1 Audio导入设置检查与优化 根据平台选择合理的音频设置,原始音频资源尽量采用未压缩WAV格式 - 移动平台对音乐音效统一采用单通道设置(Force to Mono),并将音乐采样频率设置为22050Hz - 移动平台大多数声音尽量采用Vorbis压缩设置&#xff0…

JDBC和数据库应用总结

文章目录 1. JDBC介绍2. 相关jar包引入3. JDBC与数据库基本连接4. JDBC API 详解4.1 Connection 接口4.2 Statement 接口4.3 ResultSet 5. PreparedStatement 详解 1. JDBC介绍 JDBC是一套标准接口,这套接口用于操作所有的数据库,不同的数据库厂商对迎合…

《kafka 核心技术与实战》课程学习笔记(六)

生产者消息分区机制原理剖析 为什么分区? Kafka 有主题(Topic)的概念,它是承载真实数据的逻辑容器,而在主题之下还分为若干个分区,也就是说 Kafka 的消息组织方式实际上是三级结构:主题 - 分区…

体验Vue神奇的响应式原理:让你的应用更快、更流畅

文章目录 I. 引言介绍Vue.js的响应式原理及其重要性概述本文的内容 II. 数据劫持解释什么是数据劫持Vue如何实现数据劫持示例说明 II. 依赖收集解释什么是依赖收集Vue如何实现依赖收集示例说明 IV. 派发更新解释什么是派发更新Vue如何实现派发更新示例说明 V. 响应式原理运作流…

APP/小程序嵌入游戏,游戏飞跃的赛道

APP/小程序接入游戏运营已不是新鲜事,然而,其仍具有巨大的发展潜力,尤其是社交类APP,多以加入娱乐游戏增加互动,获取目标客户,同时为产品增加变现渠道,实现双赢。 对于APP嵌入式游戏&#xff0…

【MySql】用户管理——用户管理|权限管理

文章目录 用户管理用户信息创建用户删除用户修改用户密码 数据库的权限给用户授权回收权限 用户管理 如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。 比如张三只能操作mytest这个数据库,李四只能操作msg这个…