备忘录模式:行为型模式, 当我们在做某一件事时,在做的过程中可以手动的保存时间的当前状态,当做完后感觉不太满意希望可以退回到之前的某一步继续做,这种思想就是备忘录模式的使用。
例如在编辑文件时可以使用 Ctrl + Z 就能够回到上一步,就是备忘录模式的使用。
备忘录模式又叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。
备忘录模式主要有3中角色: 1、发起者:记录当前时刻的内部状态信息,提供创建备忘录和回复备忘录的功能。 2、备忘录:负责存储发起人的内部状态,在发起人需要的时候将内部状态告知发起者。 3、管理者:对备忘录进行管理,提供保存和获取备忘录,但不对备忘录中的信息进行访问和修改。
例如:在玩游戏时游戏角色有生命力、攻击力和防御力三种内部状态。在开始之前三种状态都拥有一些数值,然后对游戏的大怪进行搏斗,消灭大怪以后,状态数据发生了变化。设对后面的数据不满意,就可以在游戏开始之前将数据进行保存,在结束之后进行恢复,然后重新对抗大怪,知道最后满意为止。
备忘录有两个等效的接口:
-
窄接口:管理者(Caretaker)对象(和其他发起人对象之外的任何对象)看到的是备忘录的窄接口(narror Interface),这个窄接口只允许他把备忘录对象传给其他的对象。
-
宽接口:与管理者看到的窄接口相反,发起人对象可以看到一个宽接口(wide Interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
备忘录模式根据内部存储方式的不同分为白盒和黑盒
-
白盒模式:备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开。
-
黑盒模式:备忘录角色对发起人对象提供一个宽接口,而为其他对象提供一个窄接口。
实现代码:
1、白盒模式
/**
* 备忘录角色
**/
public class RoleStateMemento {
private int vit;
private int atk;
private int def;
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;
}
}
/**
* 角色状态管理者类
**/
public class RoleStateCaretaker {
private RoleStateMemento roleStateMemento;
public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}
public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}
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;
}
}
/************ 测试 ********************/
public static void main(String[] args) {
System.out.println("------------大战Boss前------------");
//大战Boss前
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();
//保存进度
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setMemento(gameRole.saveState());
System.out.println("------------大战Boss后------------");
//大战Boss时,损耗严重
gameRole.fight();
gameRole.stateDisplay();
System.out.println("------------恢复之前状态------------");
//恢复之前状态
gameRole.recoverState(roleStateCaretaker.getMemento());
gameRole.stateDisplay();
}
//测试结果
------------大战Boss前------------
角色生命力:100
角色攻击力:100
角色防御力:100
------------大战Boss后------------
角色生命力:0
角色攻击力:0
角色防御力:0
------------恢复之前状态------------
角色生命力:100
角色攻击力:100
角色防御力:100
Process finished with exit code 0
2、黑盒模式
public interface Memento {
}
public class RoleStateCaretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
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(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;
}
}
}
/****** 测试 *********/
public static void main(String[] args) {
System.out.println("------------大战Boss前------------");
//大战Boss前
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();
//保存进度
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setMemento(gameRole.saveState());
System.out.println("------------大战Boss后------------");
//大战Boss时,损耗严重
gameRole.fight();
gameRole.stateDisplay();
System.out.println("------------恢复之前状态------------");
//恢复之前状态
gameRole.recoverState(roleStateCaretaker.getMemento());
gameRole.stateDisplay();
}
//测试结果
------------大战Boss前------------
角色生命力:100
角色攻击力:100
角色防御力:100
------------大战Boss后------------
角色生命力:0
角色攻击力:0
角色防御力:0
------------恢复之前状态------------
角色生命力:100
角色攻击力:100
角色防御力:100
Process finished with exit code 0