一、简介
备忘录模式提供了一种对象状态撤销的实现机制,当系统中某一个对象需要恢复到某一历史状态时可以使用备忘录模式进行设计。
备忘录又称快照模式,是行为型设计模式的一种,它的原始定义为:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复为原先保存的状态。
二、原理
备忘录模式由以下几个角色组成
①看护人:主要对备忘录进行管理
②发起人:能够进行备份的角色
③备忘录:访问权限为:默认,在同包下可以访问
三、实现
设计一个收集水果和获取金钱数的掷骰子游戏,游戏规则如下
1.游戏玩家通过扔骰子来决定下一个状态
2.当点数为1时,玩家金钱增加
3.当点数为2时,玩家金钱减少
4.当点数为6时,玩家会获得水果
5.当钱消耗到一定程度,就恢复到初始状态
1)备忘录
package com.dahai.memento;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.util.ArrayList;
import java.util.List;
/**
* 备忘录
*/
class Memento {
private int money;//玩家金币
private List<String> fruits; //玩家获取水果
public Memento(int money) {
this.money = money;
this.fruits=new ArrayList<>();
}
public int getMoney() {
return money;
}
public List<String> getFruits() {
return fruits;
}
//添加水果
public void addFruit(String fruitName){
fruits.add(fruitName);
}
}
2)玩家类
package com.dahai.memento;
import lombok.var;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Player {
private int money;//玩家金币
private List<String> fruits=new ArrayList<>(); //玩家获取水果
public static String[] fruitsName={
"苹果","香蕉","葡萄"
};
Random random=new Random();
public Player(int money) {
this.money = money;
}
//获取玩家钱
public int getMoney(){
return money;
}
//获取水果
public String getFruits(){
int i = random.nextInt(fruitsName.length - 1);
return fruitsName[i];
}
//掷骰子
public void play(){
int flag = random.nextInt(6) + 1;
if (flag==1){
System.out.println("玩家金钱增加");
this.money+=100;
} else if (flag==2) {
System.out.println("玩家金钱减少");
this.money=this.getMoney()/2;
}else if (flag==6){
System.out.println("玩家获得水果");
fruits.add(getFruits());
}else {
System.out.println("无效数字");
}
}
//创建备忘录
public Memento createMemento(){
return new Memento(this.money);
}
//恢复
public void restoreMemento(Memento memento){
this.money= memento.getMoney();
this.fruits=memento.getFruits();
}
@Override
public String toString() {
return "Player{" +
"money=" + money +
", fruits=" + fruits +
", random=" + random +
'}';
}
}
3)客户端
package com.dahai.memento;
public class Client {
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+1)+"次投掷");
System.out.println("玩家状态:"+player.toString());
player.play();
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(1000L);
}
}
四、总结
优点
①提供了一种状态恢复的实现机制,使得用户可以方便的回到一个特定的历史步骤,当新的状态无效或者存在问题的时候,可以使用暂时存储起来的备忘录,将状态复原。
②备忘录实现了对信息的封装,一个备忘录对象是一种发起者状态的表示,不会被其他代码所改动,备忘录保存了发起者的状态,采用集合存储备忘录可以实现多次撤销的操作
缺点
①资源消耗过大,如果需要保存的发起者的成员变量比较多,就不可避免需要大量的存储空间。每保存一次都需要消耗一定的系统资源。
使用场景
①需要保存一个对象在某一时刻的状态时可以使用备忘录模式
②不希望外界直接访问对象内部状态时