设计模式之备忘录模式(行为型)

1、备忘录模式定义

备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样我们就可以将该对象复原到原先保存的状态。

很多时候我们需要记录一个对象的内部状态,允许用户取消不确定或者错误的操作,恢复到他原来的状态,备忘录模式就提供了这样一种可以恢复状态的机制,可以使我们比较方便的回到某一个历史状态,比如游戏的存档、数据库的事务等

2、备忘录模式结构

设计模式之备忘录模式(行为型)_第1张图片

Originator(发起人):负责创建一个备忘录 Memento,用来记录当前时刻它的内部状态,并可以使用备忘录恢复内部状态。Originator 可以根据需要决定 Memento 存储 Originator 的哪些内部状态

import lombok.Data;

/**
 * 发起人
 */
@Data
public class Originator {

    // 需要保存的属性
    private String blood;
    private String status;

    public Originator() {
    }

    public Originator(String blood, String status) {
        this.blood = blood;
        this.status = status;
    }

    /**
     * 创建备忘录,将需要爆粗你的信息保存
     *
     * @return 备忘录对象
     */
    public Memento createMemento() {
        return new Memento(blood, status);
    }

    /**
     * 恢复备忘录,将 Memento 导入并将数据恢复
     */
    public void setMemento(Memento memento) {
        status = memento.getStatus();
        blood = memento.getBlood();
    }

    /**
     * 显示数据
     */
    public void show() {
        System.out.println("status = " + status + ",blood = " + blood);
    }
}

Memento(备忘录):负责存储 Originator 对象的内部状态

import lombok.Data;

/**
 * 备忘录
 */
@Data
public class Memento {

    private String blood;

    private String status;

    public Memento() {
    }

    public Memento(String blood, String status) {
        this.blood = blood;
        this.status = status;
    }

}

Caretaker(管理者):负责保存好备忘录 Memento,不能对备忘录内的内容进行操作或者检查

import lombok.Data;

/**
 * 管理者
 */
@Data
public class Caretaker {

    private Memento memento;

}

调用方代码

public class MementoClient {

    public static void main(String[] args) {
        // Originator 初始状态,血量 100,状态 on
        Originator originator = new Originator();
        originator.setStatus("on");
        originator.setBlood("100");
        originator.show();

        // 保存状态到管理者
        Caretaker caretaker = new Caretaker();
        Memento memento = originator.createMemento();
        caretaker.setMemento(memento);

        // 改变属性,状态 off,血量 10
        originator.setStatus("off");
        originator.setBlood("10");
        originator.show();

        // 恢复原来的状态
        originator.setMemento(caretaker.getMemento());
        originator.show();
    }

}
// status = on,blood = 100
// status = off,blood = 10
// status = on,blood = 100

备忘录模式将保存的细节封装到了 Memento 中,需要更改保存的细节的话不会影响到客户端

3、备忘录模式应用场景

  • Memento 模式适用于功能较为复杂,但需要维护或者记录属性历史的类,或者需要保存的属性只是其中的一部分,Originator 可以根据保存的 Memento 信息还原到前一状态
  • 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,可以使用备忘录模式来存储可撤销操作的状态
  • 当角色的状态改变的时候,可能这个状态无效,使用备忘录可以将这个无效的状态复原

4、游戏进度备忘

一个游戏角色有生命力、攻击力、防御力等属性,可以中途退出并存档,重新进入后恢复角色状态

4.1 代码结构图

设计模式之备忘录模式(行为型)_第2张图片

4.2 代码实现

Role:游戏角色类

import lombok.Data;

@Data
public class Role {

    /**
     * 攻击
     */
    private Integer attack;

    /**
     * 血量
     */
    private Integer blood;

    /**
     * 防御
     */
    private Integer defense;

    private void init() {
        this.defense = 100;
        this.blood = 100;
        this.attack = 5;
    }
    
    /**
     * 角色状态查看
     */
    public void show() {
        System.out.println("血量:" + blood + " 攻击:" + attack + " 防御:" + defense);
    }

    /**
     * 保存角色状态
     *
     * @return 角色状态备忘录
     */
    public RoleMemento save() {
        return RoleMemento.builder()
                .blood(blood)
                .attack(attack)
                .defense(defense)
                .build();
    }

    /**
     * 恢复角色状态
     */
    public void Recover(RoleMemento roleMemento) {
        this.defense = roleMemento.getDefense();
        this.blood = roleMemento.getBlood();
        this.attack = roleMemento.getAttack();
    }

}

RoleMemento:角色备忘录(角色状态存储)

import lombok.Builder;
import lombok.Data;

/**
 * 角色状态存储
 */
@Data
@Builder
public class RoleMemento {

    /**
     * 攻击
     */
    private Integer attack;

    /**
     * 血量
     */
    private Integer blood;

    /**
     * 防御
     */
    private Integer defense;

}

RoleCaretaker:角色状态管理

import lombok.Data;

/**
 * 角色管理者
 */
@Data
public class RoleCaretaker {

    private RoleMemento roleMemento;

}

调用代码:

public class GameClient {
    public static void main(String[] args) {
        Role zhangSan = new Role();
        // 角色初始化
        zhangSan.init();
        zhangSan.show();

        // 保存进度
        RoleCaretaker roleCaretaker = new RoleCaretaker();
        // 具体保存的数据没有透传出来
        roleCaretaker.setRoleMemento(zhangSan.save());

        // 角色战斗,数据下降
        zhangSan.fight();
        zhangSan.show();

        // 恢复状态
        zhangSan.recover(roleCaretaker.getRoleMemento());
        zhangSan.show();

    }
}
// 血量:100 攻击:5 防御:100
// 血量:20 攻击:5 防御:30
// 血量:100 攻击:5 防御:100

你可能感兴趣的:(设计模式,设计模式,备忘录模式,java)