Java中23种面试常考的设计模式之备忘录模式(Memento)
之前我们讲过的设计模式在这里呦:
【面试最常见的设计模式之单例模式】
【面试最常见的设计模式之工厂模式】
接下来我们要进行学习的是:备忘录模式。
备忘录模式
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
生产生活中常用的使用场景
- 各种应用软件中,存档历史记录。
- 管理系统中,消息撤回功能。
- 棋类游戏中,悔棋。
- 普通软件中,撤销操作。
- 数据库软件中,事务管理中的,回滚操作。
- 等等等等。。。。。。。。
备忘录模式优点与缺点
优点:
1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:
消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
核心内容
备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
备忘录模式中的类 | 用途 |
---|---|
源发起类Originator| 负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态
备忘录类Memento |负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问Memento
负责人类CareTaker| 负责保存好备忘录Memento
UML类图
具体代码实现
Games类:对应的就是我们的源发起类Originator
package com.memento;
/*
* Games 游戏类(对应的属性、构造方法、每走一步的保存操作、悔棋的操作、set方法、get方法)
*/
public class Games {
private String gameName;
private int curX;
private int curY;
public Games(){
}
public Games(String gameName,int curX,int curY){
this.gameName=gameName;
this.curX=curX;
this.curY=curY;
}
// 保存记录
public GamesMemento saveMemento(){
return new GamesMemento(this);
}
// 恢复记录
public void recovery(GamesMemento gamesMemento){
this.gameName=gamesMemento.getGameName();
this.curX=gamesMemento.getCurX();
this.curY=gamesMemento.getCurY();
}
public void setGameName(String gameName){
this.gameName=gameName;
}
public String getGameName(){
return this.gameName;
}
public void setCurX(Integer curX){
this.curX=curX;
}
public Integer getCurX(){
return this.curX;
}
public void setCurY(Integer curY){
this.curY=curY;
}
public Integer getCurY(){
return this.curY;
}
public String toString(){
return "象棋棋子向X方向移动:"+this.curX+" 象棋棋子向Y方向移动:"+this.curY;
}
}
GamesMemento类:对应的就是我们的备忘录类Memento
package com.memento;
/*
* GamesMemento 游戏的存储记录类
*/
public class GamesMemento {
private String gameName;
private int curX;
private int curY;
public GamesMemento(){
}
public GamesMemento(String gameName,Integer curX,Integer curY){
this.gameName=gameName;
this.curX=curX;
this.curY=curY;
}
public GamesMemento(Games games){
this.gameName=games.getGameName();
this.curX=games.getCurX();
this.curY=games.getCurY();
}
public void setGameName(String gameName){
this.gameName=gameName;
}
public String getGameName(){
return this.gameName;
}
public void setCurX(Integer curX){
this.curX=curX;
}
public Integer getCurX(){
return this.curX;
}
public void setCurY(Integer curY){
this.curY=curY;
}
public Integer getCurY(){
return this.curY;
}
}
GamesMementoManagement类:对应的就是我们的负责人类CareTaker
package com.memento;
/*
* GamesMementoManagement 管理我们的存储记录类
* 这个类是支持扩展的,如果想要保存多个状态,那么我们可以通过集合来记录每一个游戏中保存的状态
*/
public class GamesMementoManagement {
private GamesMemento gamesMemento;
public void setGamesMemento(GamesMemento gamesMemento){
this.gamesMemento=gamesMemento;
}
public GamesMemento getGamesMemento(){
return this.gamesMemento;
}
}
测试类:
package com.memento;
public class Main {
public static void main(String[] args){
// 先创建我们的记录管理类
GamesMementoManagement gamesMementoManagement=new GamesMementoManagement();
Games games=new Games("象棋大战",4,6);
System.out.println(games);
GamesMemento gamesMemento=games.saveMemento();
gamesMementoManagement.setGamesMemento(gamesMemento);
games=new Games("象棋大战",5,9);
System.out.println(games);
System.out.println("此时走错了,想悔棋啦。。。。。。");
games.recovery(gamesMementoManagement.getGamesMemento());
System.out.println("悔棋成功,回到了最起初保存的状态!!!");
System.out.println(games);
}
}