22_備忘錄模式

  • 又叫快照模式,在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)次和,以便以后需要時可以將該對象恢復(fù)到之前的狀態(tài)。

結(jié)構(gòu)

  • 發(fā)起人(Originator)角色:記錄當(dāng)前時刻的內(nèi)部狀態(tài)信息羊精,提供創(chuàng)建備忘錄和恢復(fù)備忘錄數(shù)據(jù)的功能斯够,實(shí)現(xiàn)其他業(yè)務(wù)功能,它可以訪問備忘錄里的所有信息喧锦。
  • 備忘錄(Memento)角色:負(fù)責(zé)存儲發(fā)起人的內(nèi)部狀態(tài)读规,在需要的時候提供這些內(nèi)部狀態(tài)給發(fā)起人。
  • 管理者(Caretaker)角色:對備忘錄進(jìn)行管理燃少,提供保存與獲取備忘錄的功能束亏,但其不能對備忘錄的內(nèi)容進(jìn)行訪問與修改。

備忘錄有兩個等效的接口:

  • 窄接口:管理者(Caretaker)對象(和其他發(fā)起人對象之外的任何對象)看到的是備忘錄的窄接口(narror Interface)阵具,這個窄接口只允許他把備忘錄對象傳給其他的對象碍遍。
  • 寬接口:與管理者看到的窄接口相反,發(fā)起人對象可以看到一個寬接口(wide Interface)阳液,這個寬接口允許它讀取所有的數(shù)據(jù)怕敬,以便根據(jù)這些數(shù)據(jù)恢復(fù)這個發(fā)起人對象的內(nèi)部狀態(tài)。

案例

白箱備忘錄模式

  • 備忘錄角色對任何對象都提供一個接口帘皿,即寬接口东跪,備忘錄角色的內(nèi)部所存儲的狀態(tài)就對所有對象公開了。
// 游戲角色類(發(fā)起人角色)
// GameRole.java
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);
    }

    // 恢復(fù)角色狀態(tài)
    public void recoverState(RoleStateMemento roleStateMemento){
        // 將備忘錄對象中存儲的狀態(tài)賦值給當(dāng)前對象的成員
        this.vit = roleStateMemento.getVit();
        this.atk = roleStateMemento.getAtk();
        this.def = roleStateMemento.getDef();
    }

    // 展示狀態(tài)功能
    public void stateDisplay(){
        System.out.println("角色生命力:" + vit);
        System.out.println("角色攻擊力:" + atk);
        System.out.println("角色防御力:" + def);
    }
}

// 備忘錄角色類
// RoleStateMemento.java
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 RoleStateMemento() {
    }

    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;
    }
}

// 備忘錄對象管理角色
// RoleStateCaretaker.java
public class RoleStateCaretaker {
    // 聲明RoleStateMemento類型的變量
    private RoleStateMemento roleStateMemento;

    public void setRoleStateMemento(RoleStateMemento roleStateMemento){
        this.roleStateMemento = roleStateMemento;
    }

    public RoleStateMemento getRoleStateMemento() {
        return roleStateMemento;
    }
}

// Client.java
public class Client {
    public static void main(String[] args) {
        System.out.println("--------- 大戰(zhàn)boss前 ----------");
        // 創(chuàng)建一個游戲角色對象
        GameRole gameRole = new GameRole();
        gameRole.initState();   // 初始化狀態(tài)操作
        gameRole.stateDisplay();

        // 將該游戲角色內(nèi)部狀態(tài)進(jìn)行備份
        RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
        roleStateCaretaker.setRoleStateMemento(gameRole.saveState());

        System.out.println("--------- 大戰(zhàn)boss后 ----------");
        // 損耗嚴(yán)重
        gameRole.fight();
        gameRole.stateDisplay();

        System.out.println("--------- 恢復(fù)狀態(tài) ----------");
        gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());

        gameRole.stateDisplay();
    }
}
  • 在白箱備忘錄中鹰溜,所有的類都可以訪問到備忘錄角色狀態(tài)中的數(shù)據(jù)虽填,破壞了封裝性。

黑箱備忘錄模式

  • 備忘錄角色對發(fā)起人對象提供一個寬接口曹动,而為其他對象提供一個窄接口斋日。在Java語言中,實(shí)現(xiàn)雙重接口的辦法就是將備忘錄類設(shè)計成發(fā)起人類的內(nèi)部成員類墓陈。
// 備忘錄接口恶守,對外提供的窄接口
// Memento.java
public interface Memento {
}

// 游戲角色類(發(fā)起人角色)
// GameRole.java
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 Memento saveState(){
        return new RoleStateMemento(vit,atk,def);
    }

    // 恢復(fù)角色狀態(tài)
    public void recoverState(Memento memento){
        RoleStateMemento roleStateMemento = (RoleStateMemento)memento;
        // 將備忘錄對象中存儲的狀態(tài)賦值給當(dāng)前對象的成員
        this.vit = roleStateMemento.getVit();
        this.atk = roleStateMemento.getAtk();
        this.def = roleStateMemento.getDef();
    }

    // 展示狀態(tài)功能
    public void stateDisplay(){
        System.out.println("角色生命力:" + vit);
        System.out.println("角色攻擊力:" + atk);
        System.out.println("角色防御力:" + def);
    }

    private class RoleStateMemento implements Memento{
        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 RoleStateMemento() {
        }

        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;
        }
    }
}

// 備忘錄對象管理對象
// RoleStateCaretaker.java
public class RoleStateCaretaker {
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

// Client.java
public class Client {
    public static void main(String[] args) {
        System.out.println("--------- 大戰(zhàn)boss前 ----------");
        // 創(chuàng)建一個游戲角色對象
        GameRole gameRole = new GameRole();
        gameRole.initState();   // 初始化狀態(tài)操作
        gameRole.stateDisplay();

        // 將該游戲角色內(nèi)部狀態(tài)進(jìn)行備份
        RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
        roleStateCaretaker.setMemento(gameRole.saveState());

        System.out.println("--------- 大戰(zhàn)boss后 ----------");
        // 損耗嚴(yán)重
        gameRole.fight();
        gameRole.stateDisplay();

        System.out.println("--------- 恢復(fù)狀態(tài) ----------");
        gameRole.recoverState(roleStateCaretaker.getMemento());

        gameRole.stateDisplay();
    }
}
  • 這個案例中深化了對于接口的認(rèn)識,該段代碼本質(zhì)就是通過接口來向外部不同的類提供不同程度的內(nèi)部暴露贡必。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熬的,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赊级,更是在濱河造成了極大的恐慌,老刑警劉巖岔绸,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件理逊,死亡現(xiàn)場離奇詭異橡伞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)晋被,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門兑徘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人羡洛,你說我怎么就攤上這事挂脑。” “怎么了欲侮?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵崭闲,是天一觀的道長。 經(jīng)常有香客問我威蕉,道長刁俭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任韧涨,我火速辦了婚禮牍戚,結(jié)果婚禮上穆趴,老公的妹妹穿的比我還像新娘窥翩。我一直安慰自己,他們只是感情好常熙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布娩贷。 她就那樣靜靜地躺著第晰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪育勺。 梳的紋絲不亂的頭發(fā)上但荤,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機(jī)與錄音涧至,去河邊找鬼腹躁。 笑死,一個胖子當(dāng)著我的面吹牛南蓬,可吹牛的內(nèi)容都是我干的纺非。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼赘方,長吁一口氣:“原來是場噩夢啊……” “哼烧颖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窄陡,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤炕淮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后跳夭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涂圆,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡们镜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了润歉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模狭。...
    茶點(diǎn)故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖踩衩,靈堂內(nèi)的尸體忽然破棺而出嚼鹉,到底是詐尸還是另有隱情,我是刑警寧澤驱富,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布锚赤,位于F島的核電站,受9級特大地震影響萌朱,放射性物質(zhì)發(fā)生泄漏宴树。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一晶疼、第九天 我趴在偏房一處隱蔽的房頂上張望酒贬。 院中可真熱鬧,春花似錦翠霍、人聲如沸锭吨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽零如。三九已至,卻和暖如春锄弱,著一層夾襖步出監(jiān)牢的瞬間考蕾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工会宪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肖卧,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓掸鹅,卻偏偏與公主長得像塞帐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巍沙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評論 2 348

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

  • 定義 備忘錄模式又叫做快照模式(Snapshot Pattern)或Token模式葵姥,是對象的行為模式。 備忘錄對象...
    步積閱讀 2,932評論 0 2
  • 備忘錄模式可以在不破壞封裝的前提下句携,將一個對象的狀態(tài)捕捉(Capture)住榔幸,并在外部存儲,從而可以在需要的時候把...
    zhixin9001閱讀 274評論 0 0
  • 備忘錄模式相對還是比較好理解的,因此直接從定義開始講起 定義 備忘錄模式是指 在不破壞封裝性的前提下削咆,捕獲一個對象...
    silentleaf閱讀 548評論 0 0
  • 在閻宏博士的《JAVA與模式》一書中開頭是這樣描述備忘錄(Memento)模式的:備忘錄模式又叫做快照模式(Sna...
    Ant_way閱讀 782評論 0 0
  • 備忘錄模式是使用一個備忘錄對象把另外一個對象內(nèi)部狀態(tài)進(jìn)行保存喳篇,在適當(dāng)?shù)臅r候還原到某個狀態(tài)。如同我們記錄某件事件态辛,在...
    breezedancer閱讀 1,653評論 0 51