当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 大话设计模式笔记(十五)の备忘录模式

大话设计模式笔记(十五)の备忘录模式

2019年08月11日  | 移动技术网IT编程  | 我要评论

举个栗子

问题描述

打游戏存进度。

简单实现

gamerole

/**
 * 游戏角色
 * created by callmedevil on 2019/8/11.
 */
public class gamerole {

    // 生命力
    private int vit;
    // 攻击力
    private int atk;
    // 防御力
    private int def;

    // 状态显示
    public void statedisplay() {
        system.out.println("角色当前状态:");
        system.out.println(string.format("体力:%s", this.vit));
        system.out.println(string.format("攻击力:%s", this.atk));
        system.out.println(string.format("防御力:%s", this.def));
        system.out.println();
    }

    //  获得初始状态
    public void getinitstate() {
        // 数据通常来自本机磁盘或远程数据库
        this.vit = 100;
        this.atk = 100;
        this.def = 100;
    }

    // 战斗
    public void fight(){
        // 在与boss大战后游戏数据损耗为0
        this.vit = 0;
        this.atk = 0;
        this.def = 0;
    }

    // 省略 get set
    
}

测试

public class test {
    public static void main(string[] args) {
        // 大战boss前
        gamerole lufi = new gamerole();
        // 获得初始角色状态
        lufi.getinitstate();
        lufi.statedisplay();
        // 通过“游戏角色”新实例,保存进度
        gamerole backup = new gamerole();
        backup.setvit(lufi.getvit());
        backup.setatk(lufi.getatk());
        backup.setdef(lufi.getdef());
        // 大战boss时,损耗严重,全部为0
        lufi.fight();
        lufi.statedisplay();
        // gameover不甘心,恢复进度,重新玩过
        lufi.setvit(backup.getvit());
        lufi.setatk(backup.getatk());
        lufi.setdef(backup.getdef());
        lufi.statedisplay();
    }
}

测试结果

角色当前状态:
体力:100
攻击力:100
防御力:100

角色当前状态:
体力:0
攻击力:0
防御力:0

角色当前状态:
体力:100
攻击力:100
防御力:100

存在问题

在客户端调用这段,把整个游戏角色的细节暴露了,职责太大,需要知道游戏角色的生命力、攻击力、防御力这些细节,还要进行备份。如果以后需要增加“魔法力”或修改现有的某种力,那这部分代码就需要修改,同样恢复时也是一样的问题。

备忘录模式

定义

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

uml图

代码实现

gamerole

/**
 * 游戏角色
 * created by callmedevil on 2019/8/11.
 */
public class gamerole {

    // 属性与简单实现gamerole相同

    // 保存角色状态
    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();
    }

    // 其余方法与简单实现相同
    
}

rolestatememento

/**
 * 角色状态存储类
 * created by callmedevil on 2019/8/11.
 */
public class rolestatememento {

    // 属性与 简单实现 gamerole 相同

    // 将生命力、攻击力、防御力存入状态存储箱对象中
    public rolestatememento(int vit, int atk, int def){
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }

    // 省略 get set

}

rolestatecaretaker

/**
 * 游戏状态管理者
 * created by callmedevil on 2019/8/11.
 */
public class rolestatecaretaker {

    private rolestatememento memento;

    // 省略 get set

}

测试

public class test {
    public static void main(string[] args) {
        // 大战boss前
        gamerole lufi = new gamerole();
        lufi.getinitstate();
        lufi.statedisplay();
        // 保存游戏进度
        rolestatecaretaker stateadmin = new rolestatecaretaker();
        stateadmin.setmemento(lufi.savestate());// 将具体数据封装在了 memento中
        // 大战boss时,损耗严重
        lufi.fight();
        lufi.statedisplay();
        // 恢复状态
        lufi.recoverystate(stateadmin.getmemento());
        lufi.statedisplay();
    }
}

测试结果

与简单实现相同

总结

  • 把要保存的细节给封装在了 memento 中,哪一天要更改保存细节也不用影响客户端。
  • 备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性的一小部分时,originator 可以根据保存的 memento 信息还原到前一状态。
  • 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。
  • 使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网