备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象回复到原先保存的状态。
UML图:
月光宝盒的故事
package com.thpin.repository.designpattern; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MomentoDemo { public static void main(String[] args) { MomentPerson boy = new MomentPerson("小明"); MomentPerson girl = new MomentPerson("小红"); boy.setLover(girl); Originator originator = new Originator(boy, girl); System.out.println(originator); Caretaker caretaker = new Caretaker(); caretaker.setMemento(originator.createMomento()); MomentPerson otherBoy = new MomentPerson("小王"); otherBoy.setLover(girl); originator.getGirl().setLover(otherBoy); originator.yearsLater(5); otherBoy.setSpouse(girl); originator.getGirl().setSpouse(otherBoy); originator.yearsLater(5); originator.getGirl().setLover(boy); originator.setMomento(caretaker.getMemento()); originator.yearsLater(-10); boy = originator.getGirl(); girl = originator.getBoy(); System.out.println("小明表白小红"); girl.setLover(boy); boy.setLover(girl); originator.yearsLater(1); girl.setSpouse(boy); boy.setSpouse(girl); originator.yearsLater(10); } } /* * 发起人 */ class Originator { private MomentPerson boy; private MomentPerson girl; public Originator(MomentPerson boy, MomentPerson girl) { this.boy = boy; this.girl = girl; } // 月光宝盒存入场景 public Memento createMomento() { Memento memento = null; try {// 原型模式的深克隆,因为这boy 和 girl 是引用类型 memento = new Memento(boy.deepClone(), girl.deepClone()); } catch (Exception e) { e.printStackTrace(); } return memento; } // 波若波若蜜,打开月光宝盒 public void setMomento(Memento memento) { this.boy = memento.getBoy(); this.girl = memento.getGirl(); } public void yearsLater(int years) { System.out.println(years + "年..."); System.out.println(this); } public MomentPerson getBoy() { return boy; } public void setBoy(MomentPerson boy) { this.boy = boy; } public MomentPerson getGirl() { return girl; } public void setGirl(MomentPerson girl) { this.girl = girl; } @Override public String toString() { return "Originator [boy=" + boy + ", girl=" + girl + "]"; } } /* * 月光宝盒,也叫备忘录 它的属性只有getter没有setter 备忘录只读,不能修改 */ class Memento { private MomentPerson boy; private MomentPerson girl; public Memento(MomentPerson boy, MomentPerson girl) { this.boy = boy; this.girl = girl; } public MomentPerson getBoy() { return boy; } public MomentPerson getGirl() { return girl; } @Override public String toString() { return "Memento [boy=" + boy + ", girl=" + girl + "]"; } } class Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } /* * 当下之人,痴情的人儿 */ class MomentPerson implements Serializable { private static final long serialVersionUID = -5993073159780881284L; private String name; private MomentPerson lover; private MomentPerson spouse; public MomentPerson(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public MomentPerson getLover() { return lover; } public void setLover(MomentPerson lover) { if (spouse != null) System.out.println("不可能了,本人已结婚..."); else this.lover = lover; } public MomentPerson getSpouse() { return spouse; } public void setSpouse(MomentPerson spouse) { setLover(null); this.spouse = spouse; } // 深克隆 public MomentPerson deepClone() throws Exception { // 将对象写入流中 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(this); // 将对象从流中取出 ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (MomentPerson) ois.readObject(); } @Override public String toString() { return "MomentPerson [name=" + name + ", lover=" + (lover != null ? lover.getName() : null) + ", spouse=" + (spouse != null ? spouse.getName() : null) + "]"; } }结果:
Originator [boy=MomentPerson [name=小明, lover=小红, spouse=null], girl=MomentPerson [name=小红, lover=null, spouse=null]]5年...Originator [boy=MomentPerson [name=小明, lover=小红, spouse=null], girl=MomentPerson [name=小红, lover=小王, spouse=null]]5年...Originator [boy=MomentPerson [name=小明, lover=小红, spouse=null], girl=MomentPerson [name=小红, lover=null, spouse=小王]]不可能了,本人已结婚...-10年...Originator [boy=MomentPerson [name=小明, lover=小红, spouse=null], girl=MomentPerson [name=小红, lover=null, spouse=null]]小明表白小红1年...Originator [boy=MomentPerson [name=小明, lover=小红, spouse=null], girl=MomentPerson [name=小红, lover=小明, spouse=null]]10年...Originator [boy=MomentPerson [name=小明, lover=null, spouse=小红], girl=MomentPerson [name=小红, lover=null, spouse=小明]]
曾经有一份真挚的爱情放在我面前,我没有去珍惜,直到失去后我才追悔莫及。人生中最痛苦的事莫过于此,如果一切可以重来,我会对那个女孩说:我爱你!如果要我在这份爱上加上一个期限——那会是一万年!
使用备忘录的时候别忘记对象的备份是消耗内存的。
程序里你可以使用备忘录保存重要的状态,大话西游里至尊宝可以使用月光宝盒回到过去。毕竟这些都是假的!人生不复返珍惜眼前人,或许身边那个人才值得你拥有。
