备忘录模式(Memento Pattern)

备忘录模式定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态


public class Knight {
    private int health = 100;
    private int magic = 50;

    public void fight(){
        health = 0;
        magic = 0;
    }

    public void showState(String desc){
        StringBuilder builder = new StringBuilder();
        builder.append(desc).append("----")
                .append("health:").append(health).append(",")
                .append("magic:").append(magic);
        System.out.println(builder.toString());
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public int getMagic() {
        return magic;
    }

    public void setMagic(int magic) {
        this.magic = magic;
    }
}
public class Game {

    public void play(){
        Knight knight = new Knight();

        // 存档
        Knight backup = new Knight();
        backup.setHealth(knight.getHealth());
        backup.setMagic(knight.getMagic());

        // 打boss
        knight.showState("before fight");
        knight.fight();
        knight.showState("after fight");

        // 挑战失败读档
        if(knight.getHealth() == 0){
            knight.setHealth(backup.getHealth());
            knight.setMagic(backup.getMagic());
            knight.showState("after reload");
        }
    }

    public static void main(String[] args){
        Game game = new Game();
        game.play();
    }
}

对于Game类来说,只要骑士的状态可以恢复就好,不需要了解哪些属性需要恢复,否则一旦骑士的状态发生了变更,Game类也需要进行修改

修改骑士类,提供存档、读档方法


public class Knight {
    private int health = 100;
    private int magic = 50;

    public void fight(){
        health = 0;
        magic = 0;
    }

    public void showState(String desc){
        StringBuilder builder = new StringBuilder();
        builder.append(desc).append("----")
                .append("health:").append(health).append(",")
                .append("magic:").append(magic);
        System.out.println(builder.toString());
    }

    public Knight save(){
        Knight backup = new Knight();
        backup.setHealth(this.health);
        backup.setMagic(this.magic);
        return backup;
    }

    public void reload(Knight backup){
        this.health = backup.getHealth();
        this.magic = backup.getMagic();
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public int getMagic() {
        return magic;
    }

    public void setMagic(int magic) {
        this.magic = magic;
    }
}
public class Game {

    public void play(){
        Knight knight = new Knight();

        // 存档
        Knight backup = knight.save();

        // 打boss
        knight.showState("before fight");
        knight.fight();
        knight.showState("after fight");

        // 挑战失败读档
        if(knight.getHealth() == 0){
            knight.reload(backup);
            knight.showState("after reload");
        }
    }

    public static void main(String[] args){
        Game game = new Game();
        game.play();
    }
}

通过将需要备份的骑士对象的状态复制到新创建的骑士对象来完成存档操作,由于新的骑士对象拥有骑士类的所有方法,错误的 方法调用将导致备份的骑士状态被改变

因此使用骑士类来备份骑士的状态不是最好的方式,我们可以增加新的备份类,专门用来存放需要备份的骑士状态,同时将该备份类设计为不可修改,避免错误的方法调用导致备份数据异常


public class Memo {
    private int health;
    private int magic;

    public Memo(int health, int magic){
        this.health = health;
        this.magic = magic;
    }

    public int getHealth() {
        return health;
    }

    public int getMagic() {
        return magic;
    }
}
public class Knight {
    private int health = 100;
    private int magic = 50;

    public void fight(){
        health = 0;
        magic = 0;
    }

    public void showState(String desc){
        StringBuilder builder = new StringBuilder();
        builder.append(desc).append("----")
                .append("health:").append(health).append(",")
                .append("magic:").append(magic);
        System.out.println(builder.toString());
    }

    public Memo save(){
        Memo backup = new Memo(this.health, this.magic);
        return backup;
    }

    public void reload(Memo backup){
        this.health = backup.getHealth();
        this.magic = backup.getMagic();
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public int getMagic() {
        return magic;
    }

    public void setMagic(int magic) {
        this.magic = magic;
    }
}
public class Game {

    public void play(){
        Knight knight = new Knight();

        // 存档
        Memo backup = knight.save();

        // 打boss
        knight.showState("before fight");
        knight.fight();
        knight.showState("after fight");

        // 挑战失败读档
        if(knight.getHealth() == 0){
            knight.reload(backup);
            knight.showState("after reload");
        }
    }

    public static void main(String[] args){
        Game game = new Game();
        game.play();
    }
}

在我们玩游戏的时候,经常会存档多个备份,当然可以通过改造Memo类来实现这个功能,但是这里我选择创建一个新的类来专门管理所有的备份


public class MemoManager {
    private Map<String, Memo> memos = new HashedMap();

    public Memo get(String name){
        return memos.get(name);
    }

    public void set(String name, Memo memo){
        memos.put(name, memo);
    }
}
public class Game {
 
    public void play(){
        Knight knight = new Knight();
        MemoManager memoManager = new MemoManager();

        // 存档
        Memo backup = knight.save();
        memoManager.set("back1", backup);

        // 打boss
        knight.showState("before fight");
        knight.fight();
        knight.showState("after fight");

        // 挑战失败读档
        if(knight.getHealth() == 0){
            knight.reload(memoManager.get("back1"));
            knight.showState("after reload");
        }
    }

    public static void main(String[] args){
        Game game = new Game();
        game.play();
    }
}
Knight类和Memo类保持不变,经过这番改造后,整个代码结构已经完全符合备忘录模式的定义了

备忘录模式类图如下:



猜你喜欢

转载自blog.csdn.net/a19881029/article/details/80872915
今日推荐