设计模式之 备忘录模式

备忘录模式(Memento Pattern),简单来说用于保存一个对象,并且是保存在这个对象的外部,以便后期在需要的时候进行还原。

更准确的说是保存一个对象的内部状态,并在这个对象之外进行保存,在需要的时候对备份对象进行状态还原。

备忘录模式可以用于游戏存档,比如我们玩游戏刚通过一关,你要做的肯定是先存档,你也不想游戏中一会挂掉,从头再来吧。

我们今天就以游戏中英雄打Boss为例,来演示代码,代码也非常简单。

1、新建一个备份类,用于存档,也就是备份状态。

package com.itzhimei.study.design.memento;

/**
 * www.itzhimei.com
 * 备忘录模式--备份角色
 */
public class Memento {

    private int blood;

    public Memento(int blood) {
        this.blood = blood;
    }

    public int getBlood() {
        return blood;
    }

    public void setBlood(int blood) {
        this.blood = blood;
    }
}

2、新建Hero,用来作为你操作的人物。

package com.itzhimei.study.design.memento;

/**
 * www.itzhimei.com
 * 备忘录模式--原始角色
 */
public class Hero {

    //英雄血量
    private int blood;

    public Hero(int blood) {
        this.blood = blood;
    }

    /**
     * 存档
     * @return
     */
    public Memento saveFile() {
        System.out.println("存档创建中...");
        return new Memento(this.blood);
    }

    /**
     * 读档 还原血量
     * @param memento
     */
    public void restoreFromMemento(Memento memento) {
        System.out.println("读档恢复中...");
        this.blood = memento.getBlood();
    }

    public void setBlood(int blood) {
        this.blood = blood;
    }

    public int getBlood() {
        return blood;
    }
}

Hero中提供存档和恢复方法。

3、新建还原类

package com.itzhimei.study.design.memento;

/**
 * www.itzhimei.com
 * 备忘录模式 还原角色
 */
public class CareTaker {

    private Memento memento;

    public Memento getMemento() {
        return  memento;
    }

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

4、测试

package com.itzhimei.study.design.memento;

import java.util.Random;

/**
 * www.itzhimei.com
 * 备忘录模式测试
 */
public class Client {

    public static void main(String[] args) {
        //初始化英雄血量100
        Hero hero = new Hero(100);
        CareTaker careTaker = new CareTaker();

        //挑战前先存档
        careTaker.setMemento(hero.saveFile());
        //开始挑战Boss
        fight(hero);

        if(hero.getBlood() >0) {
            System.out.println("挑战Boss成功,剩余血量"+hero.getBlood());
        } else {
            System.out.println("挑战Boss失败,读档恢复血量");
            hero.restoreFromMemento(careTaker.getMemento());
            System.out.println("读档恢复完成,英雄当前血量:"+hero.getBlood());
        }

    }

    /**
     * 挑战Boss
     * @param hero
     */
    public static void fight(Hero hero) {
        Random r = new Random();
        for(int i=0; i<3; i++) {
            //模拟boss伤害,每次最高500,能抗住Boss三次攻击,血量大于0即为胜利
            int v = r.nextInt(500);
            System.out.println("Boss本次输出伤害:"+v);
            hero.setBlood(hero.getBlood()-v);
        }
    }
}

输出结果:

存档创建中...
Boss本次输出伤害:302
Boss本次输出伤害:84
Boss本次输出伤害:216
挑战Boss失败,读档恢复血量
读档恢复中...
读档恢复完成,英雄当前血量:100

类关系图: