总纲
- 设计原则:遵循迪米特、开闭原则
- 常用场景:需要在对象的外部保存该对象的内部状态
- 使用概率:5%
- 复杂度:中
- 变化点:无
- 选择关键点:是否可以在必要的时候捕捉到对象的内部状态
- 逆鳞:大对象的备份
- 定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
- 优点
1. 发起人备份自己的状态不需要自己管理,可以备份到外部,这样可以很好的保持封装的边界,这样做的意义在于可以给外部提供一个简单的操作该对象内部状态的接口。保持封装的边界这应该算是最重要的优点了。
2. 发起人状态的备份与恢复,发起人自身不需要管理与操作,而是由客户端自行按需要处理。
3. 如果发起人的状态出现问题,可以很轻松的恢复。
- 缺点
- 如果全部备份发起人的状态,或者其中有占用内存较大的属性(比如一个长数组),则会让备忘录模式的使用代价昂贵。
- 由于备份的信息是由发起人自己提供的,所以管理者无法预知备份的信息的大小,所以在客户端使用时,可能一个操作占用了很大的内存,但客户端并不知晓。
- 当发起人的状态改变的时候,有可能这个状态无效。如果状态改变的成功率不高的话,可以采取“假如”协议模式。“假如”的意思是指,我们将一直假如状态的改变会失败,从而对此做出一系列准备的工作。不过很明显,如果状态改变的成功率很高,则这样做的收益甚微。
备忘录模式
![](https://img.haomeiwen.com/i15057487/50d09ad9edbee806.png)
备忘录模式uml类图.png
public class Soul {
private Map<Person, Memory> memoryMap = new HashMap<Person, Memory>();
//抽离或者说搜集一个人的记忆
public void pullAwayMemory(Person person){
memoryMap.put(person, person.getMemory());
}
//强行将一个人的记忆固定在某一刻
public void forceFixMemory(Person person){
if (memoryMap.containsKey(person)) {
person.setMemory(memoryMap.get(person));
}
}
}
public class Person {
private String name;
private List<String> storyList;
public Person(String name){
this.name = name;
storyList = new ArrayList<String>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getStoryList() {
return Collections.unmodifiableList(storyList);
}
public void addStory(String history) {
this.storyList.add(history);
}
/* 新增 */
//获取记忆
public Memory getMemory(){
Memory memory = new Memory();
memory.setStoryList(new ArrayList<String>(storyList));
return memory;
}
//恢复记忆
public void setMemory(Memory memory){
storyList = memory.getStoryList();
}
/* 新增 */
public String toString(){
StringBuffer stringBuffer = new StringBuffer(name + "的记忆:\n");
for(String memory : storyList){
stringBuffer.append(memory).append("\n");
}
return stringBuffer.toString();
}
}
//记忆类(备忘录)
public class Memory {
private List<String> storyList;
public List<String> getStoryList() {
return storyList;
}
public void setStoryList(List<String> storyList) {
this.storyList = storyList;
}
}
public class Client {
public static void main(String[] args) {
Soul soul = new Soul();
Person personA = new Person("看守所人员A");
Person personB = new Person("看守所人员B");
//看守所人员A的记忆
personA.addStory("小时候偷换男女厕所的牌子");
personA.addStory("用裤衩上的猴皮筋做成弹弓打别人家玻璃,结果被弹了小JJ");
//看守所人员B的记忆
personB.addStory("小时候比谁尿的更高更远,我得了第一,只是不小心方向变成了直上直下,尿到了自己脸上");
personB.addStory("有一次正上课,不小心放了个屁,结果带出了点杂物,满教室都是臭味熏天");
System.out.println(personA);
System.out.println(personB);
//灵魂(管理者)抽离两个人之前的记忆
soul.pullAwayMemory(personA);
soul.pullAwayMemory(personB);
//两个人看到了小左的技能和面貌
personA.addStory("有一个人竟然可以飞行,记忆中还记得他的样貌");
personB.addStory("有一个人竟然可以飞行,记忆中还记得他的样貌");
System.out.println(personA);
System.out.println(personB);
//强行恢复记忆
soul.forceFixMemory(personA);
soul.forceFixMemory(personB);
System.out.println(personA);
System.out.println(personB);
}
}
网友评论