欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计模式之备忘录模式

程序员文章站 2022-03-09 21:45:27
很多人都玩游戏,也知道游戏进度保存的重要性。一般我们在与boss决战之前就会保存自己角色的数据,万一被boss打得屁股尿流挂掉了,我们也可以从之前保存的进度重新开始。 我们来程序模拟一下游戏进度的保存。 第一版,简单的实现: 代码无错未必优。这段代码的问题主要在于客户端的调用,这样写就是等于把整个游 ......

很多人都玩游戏,也知道游戏进度保存的重要性。一般我们在与boss决战之前就会保存自己角色的数据,万一被boss打得屁股尿流挂掉了,我们也可以从之前保存的进度重新开始。

我们来程序模拟一下游戏进度的保存。

第一版,简单的实现:

public class GameRole {
    //生命力
    private int vit;
    //攻击力
    private int atk;
    //防御力
    private int 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;
    }
    //状态显示
    public void stateDisplay(){
        System.out.println("角色当前状态:");
        System.out.println("体力:" + this.vit);
        System.out.println("攻击力:" + this.atk);
        System.out.println("防御力:" + this.def);
    }
    //获得初始状态,数据通常来自本机磁盘或远程数据库
    public void getInitState(){
        this.vit = 100;
        this.atk = 100;
        this.def = 100;
    }
    //战斗,与boss大战后游戏数据损耗为零
    public void fight(){
        this.vit = 0;
        this.atk = 0;
        this.def = 0;
    }
}
public class Test {

    public static void main(String[] args) {
        // 大战前
        GameRole lixiaoyao = new GameRole();
        lixiaoyao.getInitState();
        lixiaoyao.stateDisplay();
        //保存进度
        System.out.println("----------------");
        GameRole backup = new GameRole();
        backup.setVit(lixiaoyao.getVit());
        backup.setAtk(lixiaoyao.getAtk());
        backup.setDef(lixiaoyao.getDef());
        //大战boss,损耗严重
        System.out.println("----------------");
        lixiaoyao.fight();
        lixiaoyao.stateDisplay();
        //恢复之前的状态
        System.out.println("----------------");
        lixiaoyao.setAtk(backup.getAtk());
        lixiaoyao.setDef(backup.getDef());
        lixiaoyao.setVit(backup.getVit());
        lixiaoyao.stateDisplay();
        
    }

}

代码无错未必优。这段代码的问题主要在于客户端的调用,这样写就是等于把整个游戏角色的细节暴露给了客户端,客户端的职责就太大了。需要知道生命力,攻击力,防御力的细节,还要对他进行备份等等。显然,我们希望把存取游戏进度的细节封装起来,而且最好封装在外部的类中,以体现职责分离。这里需要用到一个新的设计模式-备忘录模式。

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

设计模式之备忘录模式

Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或需要保存的属性只是众多属性中的一部分时,Originator可以根据保存的Memento信息还原到之前的状态。比如在某个系统使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销的操作状态。

第二版,游戏进度备忘

public class GameRole1 {
    //生命力
    private int vit;
    //攻击力
    private int atk;
    //防御力
    private int 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;
    }
    //保存角色状态
    public RoleStateMemoto saveState(){
        return new RoleStateMemoto(vit,atk,def);
    }
    //恢复角色状态
    public void recoveryState(RoleStateMemoto memoto){
        this.vit = memoto.getVit();
        this.atk = memoto.getDef();
        this.def = memoto.getDef();
    }
    //状态显示
        public void stateDisplay(){
            System.out.println("角色当前状态:");
            System.out.println("体力:" + this.vit);
            System.out.println("攻击力:" + this.atk);
            System.out.println("防御力:" + this.def);
        }
        //获得初始状态,数据通常来自本机磁盘或远程数据库
        public void getInitState(){
            this.vit = 100;
            this.atk = 100;
            this.def = 100;
        }
        //战斗,与boss大战后游戏数据损耗为零
        public void fight(){
            this.vit = 0;
            this.atk = 0;
            this.def = 0;
        }
}
public class RoleStateMemoto {
    //生命力
        private int vit;
        //攻击力
        private int atk;
        //防御力
        private int def;
        public RoleStateMemoto(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;
        }
}
public class RoleStateCareTaker {
    private RoleStateMemoto memoto;

    public RoleStateMemoto getMemoto() {
        return memoto;
    }

    public void setMemoto(RoleStateMemoto memoto) {
        this.memoto = memoto;
    }
}
public class Test2 {

    public static void main(String[] args) {
        //大战boss前
        GameRole1 lixiaoyao = new GameRole1();
        lixiaoyao.getInitState();
        lixiaoyao.stateDisplay();
        
        //保存进度
        RoleStateCareTaker stateAdmin = new RoleStateCareTaker();
        stateAdmin.setMemoto(lixiaoyao.saveState());
        
        //大战boss时,损耗严重
        lixiaoyao.fight();
        lixiaoyao.stateDisplay();
        
        //恢复之前的状态
        lixiaoyao.recoveryState(stateAdmin.getMemoto());
        lixiaoyao.stateDisplay();
        
    }

}