1. 备忘录模式(Command Pattern)
1.1 介绍
-
意图 :在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
-
主要解决 :所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
-
如何解决 :通过一个备忘录类专门存储对象状态。
-
关键代码 :客户不与备忘录类耦合,与备忘录管理类耦合
1.2 优缺点
优点
-
给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态
-
实现了信息的封装,使得用户不需要关心状态的保存细节
缺点
- 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
1.3 实现场景
- 需要保存/恢复数据的相关状态场景。
- 提供一个可回滚的操作
1.4 注意事项
-
为了符合迪米特原则,还要增加一个管理备忘录的类
-
为了节约内存,可使用原型模式+备忘录模式。
2. 案例实现
虽然说没有拿到宝藏,但是经历的这一切都是很有意义的,宝藏守卫拿出魔法相机,和我们合影以保存这一难忘时刻,当我们想起来答案时,对着照片大喊:“我是要成为海贼王的男人”,就可以直接传送到这里继续答题。
public class Me {
private boolean smile = false;
public void smile() {
smile = true;
System.out.println("我笑了");
}
}
public class Friend {
}
public class Guard {
}
// 历史状态
public class State {
private Me me;
private Friend friend;
private Guard guard;
public State(Me me, Friend friend, Guard guard) {
this.me = me;
this.friend = friend;
this.guard = guard;
}
}
public class MagicCamera {
private List<State> mementoList = new ArrayList<>(); // 历史记录
public void add(State state){
mementoList.add(state);
}
public State get(int index){
return mementoList.get(index);
}
}
public class Memento {
public static void main(String[] args) {
Me me = new Me();
Friend friend = new Friend();
Guard guard = new Guard();
MagicCamera magicCamera = new MagicCamera();
magicCamera.add(new State(me, friend, guard)); // 拍照
me.smile();
magicCamera.add(new State(me, friend, guard));
}
}
3. 源码实现
- 需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
- 需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,idea等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。