備忘錄模式(Memento Pattern)保存一個對象的某個狀態(tài)躺同,以便在適當?shù)臅r候恢復對象。備忘錄模式屬于行為型模式丸逸。
模式定義
?所謂備忘錄模式就是在不破壞封裝的前提下蹋艺,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)黄刚,這樣可以在以后將這個對象恢復到原先保存的狀態(tài)捎谨。
模式結(jié)構(gòu)
備忘錄模式主要包含以下幾個角色:
?Originator(發(fā)起人):負責創(chuàng)建一個備忘錄Memento,用以記錄當前時刻它的內(nèi)部狀態(tài)憔维,并可使用備忘錄恢復狀態(tài)涛救。Originator可根據(jù)需求決定Memento存儲Originator的哪些內(nèi)部狀態(tài)。
?Memento(備忘錄):負責存儲Originator對象的內(nèi)部狀態(tài)业扒,并可防止Originator以外的其他對象訪問備忘錄Memento检吆。備忘錄有兩個接口,Caretaker只能看到備忘錄的窄接口程储,它只能將備忘錄傳遞給其他對象蹭沛。Originator能夠看到一個寬接口章鲤,允許它訪問返回到先前狀態(tài)所需的所有數(shù)據(jù)摊灭。
?Caretaker(管理者):負責保存好備忘錄Memento败徊,不能對備忘錄的內(nèi)容進行操作或檢查凤粗。
備忘錄基本代碼
?發(fā)起人(Originator)類
public class Originator {
//需要保存的屬性
private String state;
//創(chuàng)建備忘錄,將當前需要保存的信息導入并實例化出一個Memento對象
public Memento createMemento() {
return new Memento(state);
}
//恢復備忘錄异逐,將Memento導入并將相關(guān)數(shù)據(jù)恢復
public void setMemento(Memento memento) {
this.state = memento.getState();
}
//顯示數(shù)據(jù)
public void show() {
System.out.println("state = " + state);
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
?備忘錄(Memento)類
public class Memento {
private String state;
//構(gòu)造方法捶索,將相關(guān)數(shù)據(jù)導入
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
?管理者(Caretaker)類
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
?客戶端程序
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
originator.setState("On");
originator.show();
Caretaker caretaker = new Caretaker();
caretaker.setMemento(originator.createMemento());
originator.setState("Off");
originator.show();
originator.setMemento(caretaker.getMemento());
originator.show();
}
}
?運行結(jié)果
state = On
state = Off
state = On
模式實現(xiàn)
?實現(xiàn)場景:游戲中的某個場景,一游戲角色有生命力灰瞻、攻擊力腥例、防御力等數(shù)據(jù),在打Boss前和后一定會不一樣的酝润,我們允許玩家如果感覺與Boss決斗的效果不理想可以讓游戲恢復到?jīng)Q斗之前燎竖。
?代碼結(jié)構(gòu)圖
?游戲角色類
public class GameRole {
private int vit; //生命力
private int atk; //攻擊力
private int def; //防御力
//初始化狀態(tài)
public void initState() {
this.vit = 100;
this.atk = 100;
this.def = 100;
}
//戰(zhàn)斗
public void fight() {
this.vit = 0;
this.atk = 0;
this.def = 0;
}
//保存角色狀態(tài)
public RoleStateMemento saveState() {
return new RoleStateMemento(vit, atk, def);
}
//回復角色狀態(tài)
public void recoverState(RoleStateMemento roleStateMemento) {
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}
public void stateDisplay() {
System.out.println("角色生命力:" + vit);
System.out.println("角色攻擊力:" + atk);
System.out.println("角色防御力:" + def);
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
?游戲狀態(tài)存儲類
public class RoleStateMemento {
private int vit;
private int atk;
private int def;
public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
?角色狀態(tài)管理者類
public class RoleStateCaretaker {
private RoleStateMemento roleStateMemento;
public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}
public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}
?客戶端程序
public class Client {
public static void main(String[] args) {
System.out.println("------------大戰(zhàn)Boss前------------");
//大戰(zhàn)Boss前
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();
//保存進度
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setRoleStateMemento(gameRole.saveState());
System.out.println("------------大戰(zhàn)Boss后------------");
//大戰(zhàn)Boss時,損耗嚴重
gameRole.fight();
gameRole.stateDisplay();
System.out.println("------------恢復之前狀態(tài)------------");
//恢復之前狀態(tài)
gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
gameRole.stateDisplay();
}
}
?運行結(jié)果
------------大戰(zhàn)Boss前------------
角色生命力:100
角色攻擊力:100
角色防御力:100
------------大戰(zhàn)Boss后------------
角色生命力:0
角色攻擊力:0
角色防御力:0
------------恢復之前狀態(tài)------------
角色生命力:100
角色攻擊力:100
角色防御力:100
模式的優(yōu)缺點
優(yōu)點
實現(xiàn)了信息的封裝要销,使得用戶不需要關(guān)心狀態(tài)的保存細節(jié)构回。
給用戶提供了一種可以恢復狀態(tài)的機制,可以使用戶能夠比較方便地回到某個歷史的狀態(tài)疏咐。
缺點
- 如果類的成員變量過多纤掸,勢必會占用比較大的資源,而且每一次保存都會消耗一定的內(nèi)存凳鬓。
模式適用場景
?很多時候我們總是需要記錄一個對象的內(nèi)部狀態(tài)茁肠,這樣做的目的是為了允許用戶取消不確定或者錯誤的操作,能夠恢復到他原先的狀態(tài)缩举,使得他有"后悔藥"可吃垦梆。
文章作者:leisurexi
新博客地址:https://leisurexi.github.io
許可協(xié)議: 署名-非商業(yè)性使用-禁止演繹 4.0 國際 轉(zhuǎn)載請保留原文鏈接及作者。