1 备忘录模式介绍
备忘录模式(memento pattern)定义: 在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态.
2 备忘录模式原理
3 备忘录模式实现
/**
* 发起人角色
**/
public class Originator {
private String state = "原始对象";
private String id;
private String name;
private String phone;
public Originator() {
}
//创建备忘录对象
public Memento createMemento(){
return new Memento(id,name,phone);
}
//恢复对象
public void restoreMemento(Memento m){
this.state = m.getState();
this.id = m.getId();
this.name = m.getName();
this.phone = m.getPhone();
}
@Override
public String toString() {
return "Originator{" +
"state='" + state + '\'' +
", id='" + id + '\'' +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
'}';
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
/**
* 备忘录角色
* 访问权限为: 默认,在同包下可见(尽量保证只有发起者类可以访问备忘录类)
**/
class Memento {
private String state = "从备份对象恢复原始对象";
private String id;
private String name;
private String phone;
public Memento() {
}
public Memento(String id, String name, String phone) {
this.id = id;
this.name = name;
this.phone = phone;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Memento{" +
"state='" + state + '\'' +
", id='" + id + '\'' +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
'}';
}
}
/**
* 负责人类-获取和保存备忘录对象
**/
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
public class Client {
public static void main(String[] args) {
//创建发起人对象
Originator o1 = new Originator();
o1.setId("1");
o1.setName("spike");
o1.setPhone("13522777722");
System.out.println("========"+o1);
//创建负责人对象
Caretaker caretaker = new Caretaker();
caretaker.setMemento(o1.createMemento());
//修改
o1.setName("update");
System.out.println("========" + o1);
//从负责人对象中获取备忘录对象,实现恢复操作
o1.restoreMemento(caretaker.getMemento());
System.out.println("========" + o1);
}
}
4 备忘录模式应用实例
/**
* 备份玩家的状态
**/
class Memento {
private int money; //玩家获取的金币
ArrayList fruits; //玩家获取的水果
public Memento(int money) {
this.money = money;
this.fruits = new ArrayList();
}
//获取当前玩家的金币
public int getMoney(){
return money;
}
//获取当前玩家的水果
List getFruits(){
return (List) fruits.clone();
}
//添加水果
void addFruit(String fruit){
fruits.add(fruit);
}
}
Player玩家类,只要玩家的金币还够,就会一直进行游戏,在该类中会设置一个createMemento方法,其作用是保存当前玩家状态.还会包含一个restore撤销方法,相当于复活操作.
/**
* 玩家类
**/
public class Player {
private int money; //金币
private List<String> fruits = new ArrayList<>(); //玩家获得的水果
private static String[] fruitsName ={ //表示水果种类的数组
"苹果","葡萄","香蕉","橘子"
};
Random random = new Random();
public Player(int money) {
this.money = money;
}
//获取当前所有金币
public int getMoney(){
return money;
}
//获取一个水果
public String getFruit(){
String prefix = "";
if(random.nextBoolean()){
prefix = "好吃的";
}
//从数组中拿一个水果
String f = fruitsName[random.nextInt(fruitsName.length)];
return prefix + f;
}
//掷骰子方法
public void yacht(){
int dice = random.nextInt(6) + 1; //掷骰子
if(dice == 1){
money += 100;
System.out.println("所持有的金币增加了...");
}else if(dice == 2){
money /= 2;
System.out.println("所持有的金币减少一半");
}else if(dice == 6){ //获取水果
String fruit = getFruit();
System.out.println("获取了水果: " + fruit);
fruits.add(fruit);
}else{
//其他结果
System.out.println("无效数字,继续投掷!");
}
}
//拍摄快照
public Memento createMemento(){
Memento memento = new Memento(money);
for (String fruit : fruits) {
//判断: 只保存 '好吃的'水果
if(fruit.startsWith("好吃的")){
memento.addFruit(fruit);
}
}
return memento;
}
//撤销方法
public void restoreMemento(Memento memento){
this.money = memento.getMoney();
this.fruits = memento.getFruits();
}
@Override
public String toString() {
return "Player{" +
"money=" + money +
", fruits=" + fruits +
'}';
}
}
测试: 由于引入了备忘录模式,可以保存某个时间点的玩家状态,这样就可以对玩家进行复活操作.
public class MainApp {
public static void main(String[] args) throws InterruptedException {
//创建玩家类,设置初始金币
Player player = new Player(100);
//创建备忘录对象
Memento memento = player.createMemento();
for (int i = 0; i < 100; i++) {
//显示扔骰子的次数
System.out.println("第" + i+"次投掷!");
//显示当前玩家状态
System.out.println("当前状态: " + player);
//开启游戏
player.yacht();
System.out.println("玩家所持有的金币: " + player.getMoney() + " 元");
//复活操作
if(player.getMoney() > memento.getMoney()){
System.out.println("赚到金币,保存当前状态,继续游戏!");
memento = player.createMemento(); //更新快照
}else if(player.getMoney() < memento.getMoney() / 2){
System.out.println("所持金币不多,将游戏恢复到初始状态!");
player.restoreMemento(memento);
}
Thread.sleep(1000);
}
}
}