Java - 备忘录模式

-- 备忘录模式(Memto),备份一份数据,在需要的时候进行回滚。

使用场景:

  • 游戏读档和回档
  • 文本编辑回退(Ctrl+Z) …………

一、优劣势

优点: 

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

缺点:

  • 类的过多创建、销毁和存储都会消耗资源,不过这个问题不大

二、模式结构

引用官方结构图:

组成(角色) 作用
Originator (原生者) 需要被保存状态以便恢复的那个对象
Memento (备忘录) 对象由Originator创建,是原生者的备份
Caretaker (管理者) 负责Memento对象的保存和Originator的恢复

疑惑:既然Memento只是为了存在字段保存信息, 那么直接 clone 原生者(Originator)好像也可以啊? 这样就不用建多一个Memento类了。

三、栗子 《游戏存档》

1、Originator(原生者) - 游戏过程记录

package com.behavior.memento;


/**
 * @description: 
 * @author: ziHeng
 * @create: 2018-08-14 19:39
 **/
public class GameRecord {

    //战斗力
    private int fightingNum;
    
    //状态
    private String status;

    //存档日期(不可修改)
    private String time;

    public GameRecord(int fightingNum, String status, String time) {
        this.fightingNum = fightingNum;
        this.status = status;
        this.time = time;
    }

    //插入存档列表
    public void createMemento(){
        Memento memento = new Memento(fightingNum, status, time);
        Caretaker.getMementoMap().put(time,memento);
    }

    //存档回滚操作 roll-back
    public void mementoRollBack(Memento memento){
        fightingNum = memento.getFightingCapacity();
        status = memento.getStatus();
    }

    public int getFightingNum() {
        return fightingNum;
    }

    public void setFightingNum(int fightingNum) {
        this.fightingNum = fightingNum;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "GameRecord{" +
                "fightingNum=" + fightingNum +
                ", status='" + status + '\'' +
                ", time='" + time + '\'' +
                '}';
    }
}

2、Memento(备忘录) - 存档记录(这里将存储和获取都直接交给了容器)

package com.behavior.memento;

import lombok.Data;

/**
 * @description: 存档
 * @author: ziHeng
 * @create: 2018-08-14 19:38
 **/
@Data //lombok插件 生成get/set方法
public class Memento {

    //战斗力
    private int fightingCapacity;

    //状态
    private String status;

    //存档日期
    private String time;

    public Memento(int fightingCapacity, String status, String time) {
        this.fightingCapacity = fightingCapacity;
        this.status = status;
        this.time = time;
    }
}

3、Caretaker (管理者)

package com.behavior.memento;

import java.util.*;

/**
 * @description: 载入存档列表 - 单例(一个游戏只存在一个档列表容器)
 * @author: ziHeng
 * @create: 2018-08-14 20:24
 **/
public class Caretaker {

    private static Map<String,Memento> mementoMap;

    public static Map<String,Memento> getMementoMap(){
        if(mementoMap ==null){
            synchronized (Caretaker.class){
                if(mementoMap ==null){
                    mementoMap = new HashMap<>();
                }
            }
        }
        return mementoMap;
    }

 
}

调用Test:

package com.behavior.memento;

import java.util.Date;
import java.util.Map;

/**
 * @description: 备忘录模式
 * @author: ziHeng
 * @create: 2018-08-14 19:37
 **/
public class MementoTest {

    public static void main(String[] args) {

        Map<String, Memento> mementoMap = Caretaker.getMementoMap();

        //存档记录1
        GameRecord gameRecord1 = new GameRecord(100,"生存","01-01 01:31");
        gameRecord1.createMemento();
        ////存档记录2
        GameRecord gameRecord2 = new GameRecord(200,"生存","10-03 02:30");
        gameRecord2.createMemento();

        //列出存档信息
        for(Memento memento:mementoMap.values()){
            System.out.println("存档信息:"+memento);
        }

        System.out.println();

        gameRecord1.setStatus("死亡");
        System.out.println("死亡后:"+gameRecord1);
        //恢复存档
        //获取存档
        Memento memento = mementoMap.get("01-01 01:31");
        gameRecord1.mementoRollBack(memento);
        System.out.println("恢复存档信息:"+gameRecord1);



    }

}

猜你喜欢

转载自blog.csdn.net/weixin_39569611/article/details/81674456