了解23种设计模式之备忘录模式
什么是备忘录模式
简单来说:如果能够回到从前。。。。
每个人都有犯错的时候,都希望有种后悔药,能弥补自己的过失,让自己重新开始,但现实是残酷的。在计算机应用中,客户同样会常常犯错误,能否提供“后悔药”给他们呢?当然是可以的,而且是有必要的。这个功能由“备忘录模式”来实现。
有很多软件都实现了这个功能, Word,记事本,Eclipse,idea 在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态;还有在 IE 中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等都属于这类。
备忘录模式(Memento):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。该模式又叫快照模式。
备忘录模式结构,特点
优点:
1,提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
2,实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
3,简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
缺点:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
备忘录角色:
- 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
结构图如下:
代码实现
发起人(Originator)角色: 记录当时时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
public class Originator {
private String state;
/**
* 创建一个备忘录,将当前的需要保存的信息导入并实例化出一个Memento对象
* @param
* @return
*/
public Memento CreateMemento() {
return new Memento(state);
}
/**
* 恢复备忘录,将Memento对象导入并将相关信息恢复
* @param
* @return
*/
public void setMemento(Memento memento) {
this.state = memento.getState();
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void show(){
System.out.println("state = "+ state);
}
}
备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改
public class Caretaker {
private Memento memento;
/**
* 得到备忘录
* @return
*/
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
测试结果: 把要保存的细节封装到 Memento 中。哪天要更改保存的细节也不用影响客户端
public class MainClass {
public static void main(String[] args) {
//创建一个发起人
Originator or=new Originator();
//创建一个管理者
Caretaker cr=new Caretaker();
//改变对象内部属性,保存状态
or.setState("On");
System.out.println("初始状态:");
or.show();
cr.setMemento(or.CreateMemento());
//修改发起人的属性
or.setState("Off");
System.out.println("新的状态:");
or.show();
//恢复状态,获得对象内部属性
or.setMemento(cr.getMemento());
System.out.println("恢复状态:");
or.show();
}
}
应用实例
1,需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
2,需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。
实现游戏保存
发起人: 游戏角色 负责
public class GameRole {
//生命力
private int vitality;
//攻击力
private int Attackpower;
//防御力
private int Defense;
/**
* 创建一个角色状态
* @return
*/
public GameRoleStateMemento createMemento(){
return new GameRoleStateMemento(vitality,Attackpower,Defense);
}
/**
* 保存一个角色状态
* @return
*/
public void setMemento(GameRoleStateMemento memento){
this.vitality = memento.getVitality();
this.Attackpower = memento.getAttackpower();
this.Defense = memento.getDefense();
}
public int getVitality() {
return vitality;
}
public void setVitality(int vitality) {
this.vitality = vitality;
}
public int getAttackpower() {
return Attackpower;
}
public void setAttackpower(int attackpower) {
Attackpower = attackpower;
}
public int getDefense() {
return Defense;
}
public void setDefense(int defense) {
Defense = defense;
}
public void show(){
System.out.println("角色生命力:"+this.vitality+ " 角色攻击力:"+this.Attackpower+" 角色防御力:"+this.Defense);
}
}
备忘录,游戏角色备忘录
public class GameRoleStateMemento {
//生命力
private int vitality;
//攻击力
private int Attackpower;
//防御力
private int Defense;
public GameRoleStateMemento(int vitality, int attackpower, int defense) {
this.vitality = vitality;
Attackpower = attackpower;
Defense = defense;
}
public int getVitality() {
return vitality;
}
public void setVitality(int vitality) {
this.vitality = vitality;
}
public int getAttackpower() {
return Attackpower;
}
public void setAttackpower(int attackpower) {
Attackpower = attackpower;
}
public int getDefense() {
return Defense;
}
public void setDefense(int defense) {
Defense = defense;
}
}
管理者
public class RoleStateCaretaker {
private GameRoleStateMemento Memento;
public GameRoleStateMemento getMemento() {
return Memento;
}
public void setMemento(GameRoleStateMemento memento) {
Memento = memento;
}
}
测试结果:
public class MainClass {
public static void main(String[] args) {
GameRole gameRole=new GameRole();
RoleStateCaretaker cr=new RoleStateCaretaker();
gameRole.setVitality(2000);
gameRole.setAttackpower(9000);
gameRole.setDefense(150);
System.out.println("初始状态:");
gameRole.show();
//保存状态
cr.setMemento(gameRole.createMemento());
gameRole.setVitality(500);
gameRole.setAttackpower(5000);
gameRole.setDefense(100);
System.out.println("新的状态:");
gameRole.show();
//恢复状态
gameRole.setMemento(cr.getMemento());
System.out.println("恢复状态:");
gameRole.show();
}
}