備忘錄模式

備忘錄模式(Memento Pattern)保存一個對象的某個狀態(tài)躺同,以便在適當?shù)臅r候恢復對象。備忘錄模式屬于行為型模式丸逸。

模式定義

?所謂備忘錄模式就是在不破壞封裝的前提下蹋艺,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)黄刚,這樣可以在以后將這個對象恢復到原先保存的狀態(tài)捎谨。

模式結(jié)構(gòu)

結(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)圖

結(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)載請保留原文鏈接及作者。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仅孩,一起剝皮案震驚了整個濱河市托猩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辽慕,老刑警劉巖京腥,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異溅蛉,居然都是意外死亡公浪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門船侧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欠气,“玉大人,你說我怎么就攤上這事镜撩≡て猓” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宜鸯。 經(jīng)常有香客問我憔古,道長,這世上最難降的妖魔是什么淋袖? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任鸿市,我火速辦了婚禮,結(jié)果婚禮上适贸,老公的妹妹穿的比我還像新娘灸芳。我一直安慰自己,他們只是感情好拜姿,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布烙样。 她就那樣靜靜地躺著,像睡著了一般蕊肥。 火紅的嫁衣襯著肌膚如雪谒获。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天壁却,我揣著相機與錄音批狱,去河邊找鬼。 笑死展东,一個胖子當著我的面吹牛赔硫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盐肃,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼爪膊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了砸王?” 一聲冷哼從身側(cè)響起推盛,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谦铃,沒想到半個月后耘成,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡驹闰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年瘪菌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘹朗。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡师妙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出骡显,到底是詐尸還是另有隱情疆栏,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布惫谤,位于F島的核電站壁顶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏溜歪。R本人自食惡果不足惜若专,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝴猪。 院中可真熱鬧调衰,春花似錦、人聲如沸自阱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沛豌。三九已至趋箩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間加派,已是汗流浹背叫确。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芍锦,地道東北人竹勉。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像娄琉,于是被迫代替她去往敵國和親次乓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 開發(fā)仿真系統(tǒng)## 考慮這樣一個仿真應用车胡,功能是:模擬運行針對某個具體問題的多個解決方案檬输,記...
    七寸知架構(gòu)閱讀 2,138評論 1 50
  • 定義 備忘錄模式又叫做快照模式(Snapshot Pattern)或Token模式,是對象的行為模式匈棘。 備忘錄對象...
    步積閱讀 2,926評論 0 2
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是備忘錄模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 優(yōu)點和缺點 適用環(huán)境 模式應用 一...
    w1992wishes閱讀 584評論 0 1
  • 1.初識備忘錄模式 在不破壞封裝性的前提下丧慈,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)主卫。這樣以后就可將該對...
    王偵閱讀 466評論 0 0
  • 1972年10月12日逃默,一架飛往智利的包機遭遇風暴,不幸墜毀在安第斯山脈簇搅。機上共45人完域,有21人當場喪生。 墜毀地...
    奔的4閱讀 372評論 0 0