設計模式-備忘錄模式

備忘錄模式(Memento Pattern)保存一個對象的某個狀態,以便在適當的時候恢復對象。備忘錄模式屬於行爲型模式。java

模式定義

 所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,這樣能夠在之後將這個對象恢復到原先保存的狀態。git

模式結構

結構圖

備忘錄模式主要包含如下幾個角色:github

Originator(發起人):負責建立一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可以使用備忘錄恢復狀態。Originator可根據需求決定Memento存儲Originator的哪些內部狀態。this

Memento(備忘錄):負責存儲Originator對象的內部狀態,並可防止Originator之外的其餘對象訪問備忘錄Memento。備忘錄有兩個接口,Caretaker只能看到備忘錄的窄接口,它只能將備忘錄傳遞給其餘對象。Originator可以看到一個寬接口,容許它訪問返回到先前狀態所需的全部數據。code

Caretaker(管理者):負責保存好備忘錄Memento,不能對備忘錄的內容進行操做或檢查。對象

備忘錄基本代碼接口

 發起人(Originator)類遊戲

public class Originator {

    //須要保存的屬性
    private String state;

    //建立備忘錄,將當前須要保存的信息導入並實例化出一個Memento對象
    public Memento createMemento() {
        return new Memento(state);
    }

    //恢復備忘錄,將Memento導入並將相關數據恢復
    public void setMemento(Memento memento) {
        this.state = memento.getState();
    }

    //顯示數據
    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;

    //構造方法,將相關數據導入
    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();

    }

}

 運行結果

state = On
state = Off
state = On

模式實現

 實現場景:遊戲中的某個場景,一遊戲角色有生命力、攻擊力、防護力等數據,在打Boss前和後必定會不同的,咱們容許玩家若是感受與Boss決鬥的效果不理想可讓遊戲恢復到決鬥以前。

 代碼結構圖

結構圖

 遊戲角色類

public class GameRole {

    private int vit; //生命力
    private int atk; //攻擊力
    private int def; //防護力

    //初始化狀態
    public void initState() {
        this.vit = 100;
        this.atk = 100;
        this.def = 100;
    }

    //戰鬥
    public void fight() {
        this.vit = 0;
        this.atk = 0;
        this.def = 0;
    }

    //保存角色狀態
    public RoleStateMemento saveState() {
        return new RoleStateMemento(vit, atk, def);
    }

    //回覆角色狀態
    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;
    }
}

 遊戲狀態存儲類

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

 角色狀態管理者類

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("------------大戰Boss前------------");
        //大戰Boss前
        GameRole gameRole = new GameRole();
        gameRole.initState();
        gameRole.stateDisplay();

        //保存進度
        RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
        roleStateCaretaker.setRoleStateMemento(gameRole.saveState());
        System.out.println("------------大戰Boss後------------");
        //大戰Boss時,損耗嚴重
        gameRole.fight();
        gameRole.stateDisplay();
        System.out.println("------------恢復以前狀態------------");
        //恢復以前狀態
        gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
        gameRole.stateDisplay();

    }

}

 運行結果

------------大戰Boss前------------
角色生命力:100
角色攻擊力:100
角色防護力:100
------------大戰Boss後------------
角色生命力:0
角色攻擊力:0
角色防護力:0
------------恢復以前狀態------------
角色生命力:100
角色攻擊力:100
角色防護力:100

模式的優缺點

優勢

  • 實現了信息的封裝,使得用戶不須要關心狀態的保存細節。

  • 給用戶提供了一種能夠恢復狀態的機制,可使用戶可以比較方便地回到某個歷史的狀態。

缺點

  • 若是類的成員變量過多,勢必會佔用比較大的資源,並且每一次保存都會消耗必定的內存。

模式適用場景

 不少時候咱們老是須要記錄一個對象的內部狀態,這樣作的目的是爲了容許用戶取消不肯定或者錯誤的操做,可以恢復到他原先的狀態,使得他有"後悔藥"可吃。

文章做者:leisurexi

新博客地址:https://leisurexi.github.io/

許可協議: 署名-非商業性使用-禁止演繹 4.0 國際 轉載請保留原文連接及做者。

相關文章
相關標籤/搜索