目录
备忘录模式(Memento)
UML图
示例代码
适用场景
优缺点
备忘录模式和原型模式
例子——游戏进度存档
例子——象棋中的悔棋
本质:保存和恢复内部状态
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以后就可以利用保存的状态实施恢复。
为什么要增加一个备忘录类?
如果在Originator类中再增加一个方法来保存这个状态,则是对单一职责原则的一种破坏。
在游戏存档例子中,Gamerole类的职责就是打boss,而保留和恢复原始状态则应该由另外一个类来承担,那我们把这个类取名就叫做备忘录
Memento(备忘录):(类的设计参考发起人)
存储发起人的内部状态,根据实际需要确定备忘录类中的属性。
Caretaker(管理者):
存储一个或多个备忘录对象,但只负责存储,所以不能修改对象,也无须知道对象的实现细节。
存储多个备忘录对象时,可以使用list+泛型
//发起人类
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento CreateMemento() {
return new Memento(state);
}
//恢复状态
public void SetMemento(Memento memento) {
state=memento.getState();
}
public void show() {
System.out.println("state:"+state);
}
}
//备忘录类
public class Memento {
private String state;
public Memento(String state) {
super();
this.state = state;
}
public String getState() {
return state;
}
}
//管理者类
public class CareTaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
public class Main {
public static void main(String[] args) {
Originator o=new Originator();
o.setState("ON");//初始状态
o.show();
CareTaker c=new CareTaker();
c.setMemento(o.CreateMemento());//保存状态
o.setState("OFF");//改变状态
o.show();
o.SetMemento(c.getMemento());//恢复初始状态
o.show();
}
}
保存一个对象在某一个时刻的全部或部分状态,在以后需要时,把该对象恢复到先前的状态
优点:
缺点:
可以组合使用
在发起人对象创建备忘录对象时,如果发起人对象中全部或者大部分的状态都需要保存,一个简洁的方式就是直接克隆一个发起人对象。这时备忘录对象里存的是一个发起人对象的实例。
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
//设置初始状态
public void setInitState() {
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 memento) {
this.vit=memento.getVit();
this.atk=memento.getAtk();
this.def=memento.getDef();
}
//显示状态
public void display() {
System.out.println("vit=" + vit + ", atk=" + atk + ", def=" + def );
}
}
//角色状态存储箱
public class RoleStateMemento {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力
public RoleStateMemento(int vit, int atk, int def) {
super();
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 memento;
public RoleStateMemento getMemento() {
return memento;
}
public void setMemento(RoleStateMemento memento) {
this.memento = memento;
}
}
public class Main {
public static void main(String[] args) {
//大战前
GameRole lxy=new GameRole();
lxy.setInitState();
lxy.display();
//保存进度
RoleStateCareTaker state1=new RoleStateCareTaker();
state1.setMemento(lxy.saveState());
//大战后
lxy.fight();
lxy.display();
//恢复原状态
lxy.RecoverState(state1.getMemento());
lxy.display();
}
}
package com.chess;
//发起人
public class ChessRole {
private int x;
private int y;
private String name;
private String color;
public ChessRole(int x, int y, String name, String color) {
super();
this.x = x;
this.y = y;
this.name = name;
this.color = color;
}
public ChessMemento createMemento() {
return new ChessMemento(x,y,name,color);
}
public void getMemento(ChessMemento memento) {
if(memento==null)return;
this.x=memento.getX();
this.y=memento.getY();
this.name=memento.getName();
this.color=memento.getColor();
}
public void setState(int x, int y, String name, String color) {
this.x=x;
this.y=y;
this.name = name;
this.color = color;
}
public void show() {
System.out.println("坐标:x=" + x + ", y=" + y + ", name=" + name + ", color=" + color);
}
}
package com.chess;
public class ChessMemento {
private int x;
private int y;
private String name;
private String color;
public ChessMemento(int x, int y, String name, String color) {
super();
this.x = x;
this.y = y;
this.name = name;
this.color = color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
}
package com.chess;
import java.util.ArrayList;
public class ChessCareTaker {
private ArrayList list=new ArrayList();
public ChessCareTaker() {
list=new ArrayList();
}
public void addMemento(ChessMemento memento) {
list.add(memento);
}
public ChessMemento huiqi() {
if(list.isEmpty()) {
System.out.println("无法悔棋");
return null;
}
else {
int index=list.size();
ChessMemento memento=(ChessMemento)list.get(index-1);
list.remove(index-1);
return memento;
}
}
}
package com.chess;
public class Main {
public static void main(String[] args) {
ChessRole c1=new ChessRole(0,0,"马1","红方");
ChessCareTaker ct1=new ChessCareTaker();
ct1.addMemento(c1.createMemento());
c1.show();
c1.setState(1, 2, "马1", "红方");
ct1.addMemento(c1.createMemento());
c1.show();
c1.setState(3, 5, "象2", "红方");
c1.show();
System.out.println("悔棋一步:");
c1.getMemento(ct1.huiqi());
c1.show();
System.out.println("悔棋二步:");
c1.getMemento(ct1.huiqi());
c1.show();
}
}