18 备忘录模式

1 定义

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

2 适用场景

  • Memento模式适用于功能比较复杂的,需要维护或记录属性历史的类 or 需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
  • 有时一些对象的内部信息必须保存在对象外的地方,但是必须由对象自己读取,这时,使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽。
  • 最大的作用是:当角色的状态改变的时候,这个状态有可能无效,这时使用备忘录将状态复原。

3 缺点

如果状态数据很多很大,备忘录对象对非常消耗内存。

4 UML图

18 备忘录模式

5 例子

5.1 场景

某个游戏角色a有3个属性:生命力、攻击力、防御力。在角色a攻击角色b之前,这三个属性是一个状态值;攻击完b后,这三个属性值是另一个状态值;此时借助角色存储备忘录Memento,恢复a攻击前的状态值。

5.2 UML图

18 备忘录模式

5.3 代码

Main

public class Main {
    public static void main(String[] args) {
        GameRole gameRole=new GameRole();
        //初始状态
        gameRole.getInitState();
        gameRole.stateDisplay();

        //保存状态
        RoleStateCaretaker caretaker=new RoleStateCaretaker();
        caretaker.setMemento(gameRole.saveState());

        //作战
        gameRole.fight();
        gameRole.stateDisplay();

        //恢复状态
        gameRole.recoveryState(caretaker.getMemento());
        gameRole.stateDisplay();
    }
}

GameRole

public class GameRole {
    private int vit;//生命力
    private int atk;//攻击力
    private int def;//防御力

    //初始化状态
    public void getInitState(){
        this.vit=100;
        this.atk=100;
        this.def=100;
    }

    //状态显示
    public void stateDisplay(){
        System.out.println(String.format("生命力:%d",this.vit));
        System.out.println(String.format("攻击力:%d",this.atk));
        System.out.println(String.format("防御力:%d",this.def));
    }

    //战斗
    public void fight(){
        this.vit=21;
        this.atk=12;
        this.def=33;
    }

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

    //恢复角色状态
    public void recoveryState(RoleStateMemento memento ){
        this.vit=memento.getVit();
        this.atk=memento.getAtk();
        this.def=memento.getDef();
    }

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

RoleStateMemento

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

RoleStateCaretaker

public class RoleStateCaretaker {
    private RoleStateMemento memento;

    public RoleStateMemento getMemento() {
        return memento;
    }

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