为了防止被“杀”了祭天,学点设计模式,并总结下还是有必要的。
一:理解
- 在备忘录模式中,备忘录对象用于保存另一对象的内部状态,支持将另一对象恢复到原来的状态。
- 备忘录对象可以做到和原对象完全无关,仅做一个暂存处理,而不用修改原有对象。
二:例子
你是个富二代。
泡妞是你的日常之一。
每次你约到一个新的姑娘时,都会对其进行一番甜言蜜语,称赞对方是你见过最漂亮的女孩。
你叫来小菜帮你抽象这个称赞程序。
小菜上来就是一顿敲。
他首先抽象富二代类FuErDai来描述你。
// 富二代类
@Data
public class FuErDai {
private String theMostBeautifulGirlEverSeen;
public void sweetWord() {
System.out.println(theMostBeautifulGirlEverSeen + ",你是我见过最漂亮的女孩!");
}
}
富二代类中包含见过最漂亮的女孩属性theMostBeautifulGirlEverSeen和一个甜言蜜语sweetWord方法。
测试代码:
public class Client {
public static void main(String[] args) {
FuErDai fuErDai = new FuErDai();
fuErDai.setTheMostBeautifulGirlEverSeen("Mary");
fuErDai.sweetWord();
fuErDai.setTheMostBeautifulGirlEverSeen("Lily");
fuErDai.sweetWord();
}
}
输入/输出:
Mary,你是我见过最漂亮的女孩!
Lily,你是我见过最漂亮的女孩!
你觉得这个程序还行。
有了程序做保障,你开始肆无忌惮地追求各种女生。
有一次,你约到一个女孩,修改了theMostBeautifulGirlEverSeen属性。
然而在一夜成长之后,你发现卸妆之后的她其实并不漂亮。
于是你迫切地想把theMostBeautifulGirlEverSeen属性修改会原来那个女孩。
你求助小菜,小菜表示无能为力。
于是,你威胁小菜开发暂存功能。
在约新的女孩之前,先暂存当前认为最美的女孩。
在和新的女孩成长时,甜言蜜语sweetWord会输出新的女孩的名字。
成长之后,可以按情况决定是否恢复。
小菜觉得可以采用备忘录模式来解决这个问题。
他首先写下备忘录Memo类。
@Data
public class Memo {
private String record;
public Memo(String record) {
this.record = record;
}
}
该类只有一个属性,用于记录女孩的名字。
此外,他还建立了一个Keeper类,用于保存备忘录对象。
@Data
public class Keeper {
private Memo memo;
}
此外,他还对富二代类进行了重构。
@Data
public class FuErDaiV2 {
private String theMostBeautifulGirlEverSeen;
public void sweetWord() {
System.out.println(theMostBeautifulGirlEverSeen + ",你是我见过最漂亮的女孩!");
}
public void eatTurnGrass(Memo memo) {
theMostBeautifulGirlEverSeen = memo.getRecord();
}
public Memo record() {
return new Memo(theMostBeautifulGirlEverSeen);
}
}
在该类中,有吃回头草eatTurnGrass方法,即将备忘录上的名字设置到最美女孩的属性上,恢复暂存之前的状态。
还有记录record方法,用于生成一个新的备忘录对象。
测试代码:
public class ClientV2 {
public static void main(String[] args) {
FuErDaiV2 fuErDaiV2 = new FuErDaiV2();
Keeper keeper = new Keeper();
fuErDaiV2.setTheMostBeautifulGirlEverSeen("Mary");
fuErDaiV2.sweetWord();
keeper.setMemo(fuErDaiV2.record());
fuErDaiV2.setTheMostBeautifulGirlEverSeen("Lily");
fuErDaiV2.sweetWord();
fuErDaiV2.eatTurnGrass(keeper.getMemo());
fuErDaiV2.sweetWord();
}
}
输入/输出:
Mary,你是我见过最漂亮的女孩!
Lily,你是我见过最漂亮的女孩!
Mary,你是我见过最漂亮的女孩!
小菜把这个程序给你的时候,你开心得像个两百斤的孩子。
你终于可以毫无顾虑地约约约了,再也不怕捡了芝麻丢了西瓜了。
三:再理解
- 备忘录的作用就是为了记录,提供恢复对象属性的功能。
- 例子中的Keeper类持有memo属性,理论上可以对memo最任何操作,然而Keeper类应该只能拥有保存和读取memo的功能。
- 可以在FuErDai中建立内部类Memo,实现一个不包含任何方法的接口,提供该接口给Keeper,Keeper就不能对Memo做任何操作了。
- 例子中的FuErDai了向外提供了eatTurnGrass和record方法,也可用get和set方法替代,做到备忘录和原对象完全解耦。