ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式学习第十九节 备忘录模式

2021-01-05 16:30:36  阅读:209  来源: 互联网

标签:String 备忘录 private 第十九 roleName 设计模式 public memento


备忘录模式

概述

    基本介绍
    1、备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复带原先保存的状态。备忘录模式属于行为型模式。
    2、备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便的回退到一个特点的历史步骤,当新的状态无效或者存在问题时,可以使用暂存起来的备忘录将其恢复。
    3、备忘录对象主要用来记录一个对象的某种状态,或者默写数据,可以从备忘录对象中获取原来的数据进行恢复操作,比如:在象棋对局中悔棋的操作、游戏中节点的保存等等,可以利用备忘录模式。
    备忘录模式原理类图分析:
在这里插入图片描述
    角色分析
    1、Originator:源类,是一个普通类,可以创建一个备忘录类,并且存储它的当前状态,也可以使用备忘录来恢复其内部状态,一般需要保存内部状态的类设计为源类。
    2、Memento:备忘录,存储源类的内部状态,根据源类来决定保存那些内部状态,需要注意的是,除了源类本身和负责人类,备忘录对象不能直接供其它类使用。
    3、Caretaker:负责人类,也叫做管理者,它负责保存备忘录,但是不能对备忘录的内容进行检查和操作,负责人类中可以存储一个或多个备忘录对象,只负责存储对象,不能修改也无需知道对象的实现细节。
    代码模拟原理类图

package com.example.pattern.memento;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 备忘录模式
 */
@Setter
@Getter
public class Originator { // 源类

    private String name; // 内部属性

    private String status; // 状态

    public Originator(String name, String status) {
        this.name = name;
        this.status = status;
    }

    public Memento createMemento() { // 保存备忘录
        return new Memento(this);
    }

    public void resetMemento(Memento memento) { // 根据备忘录对象恢复源类状态
        this.status = memento.getStatus();
    }

    @Override
    public String toString() {
        return "Originator{" +
                "name='" + name + '\'' +
                ", status='" + status + '\'' +
                '}';
    }
}

@Getter
class Memento { // 备忘录类 不对外提供操作

    private String status;

    public Memento(Originator originator) {
        this.status = originator.getStatus();
    }

}

class Caretaker { // 管理类 守护着对象

    private List<Memento> mementoList;

    public void add(Memento memento) {
        if (CollectionUtils.isEmpty(mementoList)) {
            mementoList = new ArrayList<>();
        }
        mementoList.add(memento);
    }

    public Memento getMementoByIndex(int index) {
        if (CollectionUtils.isEmpty(mementoList)) {
            throw new RuntimeException("备忘录列表为空");
        }
        return mementoList.get(index);
    }

}

class Client {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Originator o = new Originator("张三", "状态1");
        System.out.println(o);
        caretaker.add(o.createMemento());
        // 变更为状态2
        o.setStatus("状态2");
        caretaker.add(o.createMemento());
        System.out.println(o);
        // 变更为状态3
        o.setStatus("状态3");
        caretaker.add(o.createMemento());
        System.out.println(o);
        // 恢复到状态1
        o.resetMemento(caretaker.getMementoByIndex(0));
        System.out.println(o);
    }
}

案例实现

    游戏角色存档问题

package com.example.pattern.memento.improve;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 使用备忘录模式实现游戏角色存档问题
 *
 * @author zjt
 * @date 2021-01-05
 */
@Getter
@Setter
public class GameRole { // 源类

    private String roleName; // 角色名称

    private String gameLevel; // 游戏关卡

    private float HP; // 生命值

    private float MP; // 法力值

    public GameRole(String roleName, String gameLevel, float HP, float MP) {
        this.roleName = roleName;
        this.gameLevel = gameLevel;
        this.HP = HP;
        this.MP = MP;
    }

    public GameMemento createGameMemento() { // 创建备忘录
        return new GameMemento(this);
    }

    public void recoverGameMemento(GameMemento memento) {
        this.roleName = memento.getRoleName();
        this.gameLevel = memento.getGameLevel();
        this.HP = memento.getHP();
        this.MP = memento.getMP();
    }

    public void exit() {
        this.roleName = null;
        this.gameLevel = null;
        this.MP = 0;
        this.HP = 0;
    }

    @Override
    public String toString() {
        return "GameRole{" +
                "roleName='" + roleName + '\'' +
                ", gameLevel='" + gameLevel + '\'' +
                ", HP=" + HP +
                ", MP=" + MP +
                '}';
    }
}

@Getter
class GameMemento { // 备忘录类

    private String roleName; // 角色名称

    private String gameLevel; // 游戏关卡

    private float HP; // 生命值

    private float MP; // 法力值

    public GameMemento(GameRole gameRole) {
        this.roleName = gameRole.getRoleName();
        this.gameLevel = gameRole.getGameLevel();
        this.HP = gameRole.getHP();
        this.MP = gameRole.getMP();
    }
}

class GameCaretaker { // 备忘录管理类

    // 只保存最近一次的存档记录,
    private Map<String, GameMemento> mementoMap = new HashMap<>();

    public void addGameMemento(GameMemento memento) { // 添加备忘录 添加存档信息
        if (null != memento) {
            mementoMap.put(memento.getRoleName(), memento);
        }
    }

    public GameMemento getGameMemento(String roleName) { // 根据角色名称获取存档信息
        if (CollectionUtils.isEmpty(mementoMap)) {
            throw new RuntimeException("存档读取失败");
        }
        GameMemento memento = mementoMap.get(roleName);
        if (memento == null) {
            throw new RuntimeException("存档读取失败");
        }
        return memento;
    }

}

class GameClient {
    public static void main(String[] args) {
        // 创建备忘录管理者
        GameCaretaker caretaker = new GameCaretaker();
        // 创建用户角色
        GameRole role1 = new GameRole("张三", "1-1", 100, 100);
        role1.setGameLevel("3-4");
        role1.setHP(50);
        role1.setMP(47);
        caretaker.addGameMemento(role1.createGameMemento());
        System.out.println(role1);
        System.out.println("用户使用张三退出了游戏");
        role1.exit();
        System.out.println(role1);
        System.out.println("--------------");
        System.out.println("用户重新进入了游戏,并使用张三选择读档");
        GameMemento memento = caretaker.getGameMemento("张三");
        role1.recoverGameMemento(memento);
        System.out.println(role1);
    }
}

总结

    备忘录模式在很多软件的使用过程中普遍存在,但是在应用软件开发中,它的使用频率并不太高,因为现在很多基于窗体和浏览器的应用软件并没有提供撤销操作。如果需要为软件提供撤销功能,备忘录模式无疑是一种很好的解决方案。在一些字处理软件、图像编辑软件、数据库管理系统等软件中备忘录模式都得到了很好的应用。
    优点
    1、它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
    2、备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。
    缺点
    1、资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。
    2、为了节约内存,备忘录模式可以和原型模式配合使用。

标签:String,备忘录,private,第十九,roleName,设计模式,public,memento
来源: https://blog.csdn.net/GayFei/article/details/112220570

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有