-- 备忘录模式(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);
}
}