一、基础简介
1、定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。便于以后将该对象恢复到原先保存的状态
2、使用场景
1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。
应用实例: 1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctri + z。 4、IE 中的后退。 4、数据库的事务管理。
3、优缺点
优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
4、模式结构分析
- Originator (发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator 可根据需要决定Memento存储Originator的哪些内部状态。
- Memento (备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker 只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator 能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
- Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。
二、模式实例
场景:玩游戏时,我们都习惯去保存游戏进度,以防备角色over后,从某一个进度接着打boss
1、Originator (发起人)
package com.mfc.design.备忘录模式;
/**
* @author MouFangCai
* @date 2019/10/18 17:18
*
* 发起人:需要 保存的对象
*/
public class GameRole_Originator {
private String name;
/**
* 生命值
*/
private int life;
/**
* 攻击力
*/
private int atk;
/**
* 当前游戏 关数 如:1-1
*/
private String level;
// 保存进度
public Role_Memento saveGame(){
return new Role_Memento(life, atk, level);
}
// 恢复角色状态
public void recoveryGame(Role_Memento role_memento){
this.life = role_memento.getLife();
this.atk = role_memento.getAtk();
this.level = role_memento.getLevel();
}
public void gameInit(String name){
setName(name);
setAtk(100);
setLife(500);
setLevel("1-1");
}
public void fight(){
setLife(getLife() - 100);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLife() {
return life;
}
public void setLife(int life) {
this.life = life;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
@Override
public String toString() {
return "当前角色信息{" +
"name='" + name + '\'' +
", life=" + life +
", atk=" + atk +
"-----当前关卡:'" + level + '\'' +
'}';
}
}
2、Memento (备忘录)
package com.mfc.design.备忘录模式;
/**
* @author MouFangCai
* @date 2019/10/18 17:27
*
* 备忘录:游戏储存箱,定义需要备忘的属性
*/
public class Role_Memento {
/**
* 我们在此保存3个属性
*/
private int life;
private int atk;
private String level;
// 将想要保存的属性 存入 储存箱中
public Role_Memento(int life, int atk, String level) {
this.life = life;
this.atk = atk;
this.level = level;
}
public int getLife() {
return life;
}
public void setLife(int life) {
this.life = life;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
}
3、Caretaker(管理者)
package com.mfc.design.备忘录模式;
/**
* @author MouFangCai
* @date 2019/10/18 17:34
*
* 游戏备忘录管理者
*/
public class Game_Caretaker {
private Role_Memento roleMemento;
public Role_Memento getRoleMemento() {
return roleMemento;
}
public void setRoleMemento(Role_Memento roleMemento) {
this.roleMemento = roleMemento;
}
}
4、客户端
package com.mfc.design.备忘录模式;
/**
* @author MouFangCai
* @date 2019/10/18 17:37
*/
public class Client_Memento {
public static void main(String[] args) {
GameRole_Originator gameRole = new GameRole_Originator();
gameRole.gameInit("拳王");
System.out.println("初始状态:" + gameRole.toString());
// 打怪
gameRole.fight();
// 保存游戏进度
Game_Caretaker gameCaretaker = new Game_Caretaker();
gameCaretaker.setRoleMemento(gameRole.saveGame());
System.out.println("保存进度:" + gameRole.toString());
// 打怪
gameRole.fight();
gameRole.fight();
System.out.println("打怪后,感觉打不过了:" + gameRole.toString());
// 恢复游戏进度
gameRole.recoveryGame(gameCaretaker.getRoleMemento());
System.out.println("恢复的进度为:" + gameRole.toString());
}
}
5、结果
初始状态:当前角色信息{name='拳王', life=500, atk=100-----当前关卡:'1-1'}
保存进度:当前角色信息{name='拳王', life=400, atk=100-----当前关卡:'1-1'}
打怪后,感觉打不过了:当前角色信息{name='拳王', life=200, atk=100-----当前关卡:'1-1'}
恢复的进度为:当前角色信息{name='拳王', life=400, atk=100-----当前关卡:'1-1'}Process finished with exit code 0
网友评论