继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用!
6.11 备忘录模式
6.11.1 定义
又称快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存此状态,以便后续需要时将该对象恢复到原先保存的状态
6.11.2 结构
- 发起人角色(originator):记录当前时刻的内部状态信息,提供创备忘录和恢复备忘录数据的功能,实现其他业务功能,可以访问备忘录里的所有信息
- 备忘录角色(memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人
- 管理者角色(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录内容进行访问与修改
- 两个等效接口:
- 窄接口:管理对象(和发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow interface),此接口仅仅运行它把备忘录对象传给其他对象
- 宽接口:发起人可以看到宽接口(wide interface),此接口运行它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态
6.11.3 案例
6.11.3.1 白箱模式
- 特点:对所有对象提供一个宽接口,违反了封闭原则
- 游戏角色
public class GameRole {
// 角色名称 private String name;
// 生命力 private int vita;
// 攻击力 private int attack;
// 防御力 private int defender; public int getVita() { return vita; } public void setVita(int vita) { this.vita = vita; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefender() { return defender; } public void setDefender(int defender) { this.defender = defender; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 初始化状态 public void initState(){ this.attack = 100; this.vita = 100; this.defender = 100; }
// 战斗 public void fight(){ this.vita -= 50; this.attack -= 50; this.defender -= 50; }
// 保存状态 public RoleStateMemento saveState(){ return new RoleStateMemento(name,vita,attack,defender); }
// 恢复角色状态 public void recoverState(RoleStateMemento roleStateMemento){
// 将备忘录对象中数据赋值给角色对象成员 this.vita = roleStateMemento.getVita(); this.attack = roleStateMemento.getAttack(); this.defender = roleStateMemento.getDefender(); }
// 展示角色属性 public void display(){ System.out.println("角色" + name + "属性:"); System.out.println("角色生命力:" + this.vita); System.out.println("角色攻击力:" + this.attack); System.out.println("角色防御力:" + this.defender); }
}
- 备忘录对象
public class RoleStateMemento { // 角色名称 private String name; // 生命力 private int vita; // 攻击力 private int attack; // 防御力 private int defender; public int getVita() { return vita; } public void setVita(int vita) { this.vita = vita; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefender() { return defender; } public void setDefender(int defender) { this.defender = defender; } public String getName() { return name; } public RoleStateMemento(String name, int vita, int attack, int defender) { this.attack = attack; this.vita = vita; this.defender = defender; this.name = name; } public RoleStateMemento() { }
}
- 备忘录管理对象
public class RoleStateManage {
// 用集合存储备忘录对象 private Map<String,RoleStateMemento> map = new HashMap<String,RoleStateMemento>();
// 添加备忘录对象 public void addRoleStateMemento(RoleStateMemento roleStateMemento){ map.put(roleStateMemento.getName(),roleStateMemento); }
// 获取备忘录对象 public RoleStateMemento getRoleStateMemento(String name){ return map.get(name); }
}
- 测试
public static void main(String[] args) { System.out.println("大战前-----------------------");
// 创建角色 GameRole gameRole = new GameRole(); gameRole.setName("张三");
// 初始化 gameRole.initState();
// 展示 gameRole.display();
// 保存状态 RoleStateMemento roleStateMemento = gameRole.saveState(); RoleStateManage roleStateManage = new RoleStateManage(); roleStateManage.addRoleStateMemento(roleStateMemento); System.out.println("大战-----------------------"); gameRole.fight();
// 展示 gameRole.display(); System.out.println("大战后-----------------------");
// 恢复状态 roleStateMemento = roleStateManage.getRoleStateMemento("张三"); gameRole.recoverState(roleStateMemento);
// 展示 gameRole.display(); }
-
结果
![![[Pasted image 20230117212002.png]]](https://img-blog.csdnimg.cn/f0906e29507a49c898dc1682a592ca4f.png)
-
类图
![![[Pasted image 20230117212119.png]]](https://img-blog.csdnimg.cn/9c99f2e88c344789a4858ba556721fce.png)
6.11.4.1 黑箱模式
- 改进:对发起任对象提供宽接口,为其它对象提供窄接口。具体是将备忘录对象设置为发起人的内部成员类
- 抽象备忘录接口,供外部访问
public interface Memento {
}
- 游戏角色
public class GameRole {
// 角色名称 private String name;
// 生命力 private int vita;
// 攻击力 private int attack;
// 防御力 private int defender; public int getVita() { return vita; } public void setVita(int vita) { this.vita = vita; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefender() { return defender; } public void setDefender(int defender) { this.defender = defender; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 初始化状态 public void initState(){ this.attack = 100; this.vita = 100; this.defender = 100; }
// 战斗 public void fight(){ this.vita -= 50; this.attack -= 50; this.defender -= 50; }
// 保存状态 public RoleStateMemento saveState(){ return new RoleStateMemento(vita,attack,defender); }
// 恢复角色状态 public void recoverState(Memento memento){ RoleStateMemento roleStateMemento = (RoleStateMemento) memento;
// 将备忘录对象中数据赋值给角色对象成员 this.vita = roleStateMemento.getVita(); this.attack = roleStateMemento.getAttack(); this.defender = roleStateMemento.getDefender(); }
// 展示角色属性 public void display(){ System.out.println("角色" + name + "属性:"); System.out.println("角色生命力:" + this.vita); System.out.println("角色攻击力:" + this.attack); System.out.println("角色防御力:" + this.defender); } //备忘录对象private class RoleStateMemento implements Memento { // 生命力 private int vita; // 攻击力 private int attack; // 防御力 private int defender; public int getVita() { return vita; } public void setVita(int vita) { this.vita = vita; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefender() { return defender; } public void setDefender(int defender) { this.defender = defender; } public RoleStateMemento(int vita, int attack, int defender) { this.attack = attack; this.vita = vita; this.defender = defender; } }
}
- 管理备忘录对象
public class RoleStateManage {
// 用集合存储备忘录对象 private Map<String, Memento> map = new HashMap<String, Memento>();
// 添加备忘录对象 public void addRoleStateMemento(String name,Memento memento){ map.put(name,memento); }
// 获取备忘录对象 public Memento getRoleStateMemento(String name){ return map.get(name); }
}
- 测试
public static void main(String[] args) { System.out.println("大战前-----------------------");
// 创建角色 GameRole gameRole = new GameRole(); gameRole.setName("张三");
// 初始化 gameRole.initState();
// 展示 gameRole.display();
// 保存状态 Memento roleStateMemento = gameRole.saveState(); RoleStateManage roleStateManage = new RoleStateManage(); roleStateManage.addRoleStateMemento("张三",roleStateMemento); System.out.println("大战-----------------------"); gameRole.fight();
// 展示 gameRole.display(); System.out.println("大战后-----------------------");
// 恢复状态 Memento memento= roleStateManage.getRoleStateMemento("张三"); gameRole.recoverState(memento);
// 展示 gameRole.display(); }
- 结果不变,同上
- 类图
![![[Pasted image 20230117214818.png]]](https://img-blog.csdnimg.cn/e2ae72ecb9b6431a806127c4088d8f56.png)
6.11.4 优缺点
6.11.4.1 优点
- 提供了一种可以恢复状态的机制,当用户需要时能方便的将数据恢复到某个历史的状态
- 实现了内部状态的封装,除了创建它的发起人外,其它对象都不能访问这些状态信息
- 简化了发起人类,发起人不需要管理和保存其内部状态的备份,所有状态信息保存在备忘录,并有管理者进行管理,复合单一职责原则
6.11.4.2 缺点
- 资源消耗大,若保存频繁或内部状态信息过多,会消耗内存
6.11.5 使用场景
- 需要保存和恢复数据的场景,如游戏存档
- 需要提供一个可回滚操作,如记事本,Word等
















