為了防止被“殺”了祭天罢吃,學(xué)點(diǎn)設(shè)計(jì)模式,并總結(jié)下還是有必要的昭齐。
一:理解
- 在備忘錄模式中尿招,備忘錄對(duì)象用于保存另一對(duì)象的內(nèi)部狀態(tài),支持將另一對(duì)象恢復(fù)到原來(lái)的狀態(tài)阱驾。
- 備忘錄對(duì)象可以做到和原對(duì)象完全無(wú)關(guān)就谜,僅做一個(gè)暫存處理,而不用修改原有對(duì)象里覆。
二:例子
你是個(gè)富二代丧荐。
泡妞是你的日常之一。
每次你約到一個(gè)新的姑娘時(shí)喧枷,都會(huì)對(duì)其進(jìn)行一番甜言蜜語(yǔ)虹统,稱贊對(duì)方是你見過最漂亮的女孩。
你叫來(lái)小菜幫你抽象這個(gè)稱贊程序隧甚。
小菜上來(lái)就是一頓敲车荔。
他首先抽象富二代類FuErDai來(lái)描述你。
// 富二代類
@Data
public class FuErDai {
private String theMostBeautifulGirlEverSeen;
public void sweetWord() {
System.out.println(theMostBeautifulGirlEverSeen + ",你是我見過最漂亮的女孩!");
}
}
富二代類中包含見過最漂亮的女孩屬性theMostBeautifulGirlEverSeen和一個(gè)甜言蜜語(yǔ)sweetWord方法戚扳。
測(cè)試代碼:
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,你是我見過最漂亮的女孩!
你覺得這個(gè)程序還行忧便。
有了程序做保障,你開始肆無(wú)忌憚地追求各種女生帽借。
有一次珠增,你約到一個(gè)女孩,修改了theMostBeautifulGirlEverSeen屬性宜雀。
然而在一夜成長(zhǎng)之后切平,你發(fā)現(xiàn)卸妝之后的她其實(shí)并不漂亮握础。
于是你迫切地想把theMostBeautifulGirlEverSeen屬性修改會(huì)原來(lái)那個(gè)女孩辐董。
你求助小菜,小菜表示無(wú)能為力禀综。
于是简烘,你威脅小菜開發(fā)暫存功能苔严。
在約新的女孩之前,先暫存當(dāng)前認(rèn)為最美的女孩孤澎。
在和新的女孩成長(zhǎng)時(shí)届氢,甜言蜜語(yǔ)sweetWord會(huì)輸出新的女孩的名字。
成長(zhǎng)之后覆旭,可以按情況決定是否恢復(fù)退子。
小菜覺得可以采用備忘錄模式來(lái)解決這個(gè)問題。
他首先寫下備忘錄Memo類型将。
@Data
public class Memo {
private String record;
public Memo(String record) {
this.record = record;
}
}
該類只有一個(gè)屬性寂祥,用于記錄女孩的名字。
此外七兜,他還建立了一個(gè)Keeper類丸凭,用于保存?zhèn)渫泴?duì)象。
@Data
public class Keeper {
private Memo memo;
}
此外腕铸,他還對(duì)富二代類進(jìn)行了重構(gòu)惜犀。
@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方法狠裹,即將備忘錄上的名字設(shè)置到最美女孩的屬性上虽界,恢復(fù)暫存之前的狀態(tài)。
還有記錄record方法酪耳,用于生成一個(gè)新的備忘錄對(duì)象浓恳。
測(cè)試代碼:
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,你是我見過最漂亮的女孩!
小菜把這個(gè)程序給你的時(shí)候,你開心得像個(gè)兩百斤的孩子碗暗。
你終于可以毫無(wú)顧慮地約約約了颈将,再也不怕?lián)炝酥ヂ閬G了西瓜了。
三:再理解
- 備忘錄的作用就是為了記錄言疗,提供恢復(fù)對(duì)象屬性的功能晴圾。
- 例子中的Keeper類持有memo屬性,理論上可以對(duì)memo最任何操作噪奄,然而Keeper類應(yīng)該只能擁有保存和讀取memo的功能死姚。
- 可以在FuErDai中建立內(nèi)部類Memo,實(shí)現(xiàn)一個(gè)不包含任何方法的接口勤篮,提供該接口給Keeper都毒,Keeper就不能對(duì)Memo做任何操作了。
- 例子中的FuErDai了向外提供了eatTurnGrass和record方法碰缔,也可用get和set方法替代账劲,做到備忘錄和原對(duì)象完全解耦。