zoukankan      html  css  js  c++  java
  • Java设计模式之从[暗黑破坏神存档点]分析备忘录(Memento)模式

      在大部分游戏中,都有一个“存档点”的概念。比如,在挑战boss前,游戏会在某个地方存档,假设玩家挑战boss失败,则会从这个存档点開始又一次游戏。因此,我们能够将这个“存档点”当成是一个备忘录,我们将此时玩家全部的状态保存下来,以便之后的读取。

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

      一个简单的样例,如果玩家在暗黑破坏神中准备挑战Boss巴尔,玩家携带了10瓶药剂,而且在巴尔的门前“世界之石”存了档,玩家在挑战Boss时使用了1瓶药剂,后来挑战失败了,于是他又一次读档,再次回到了世界之石,此时他身上携带的药剂数量仍然应该为10瓶。

      详细的代码例如以下:

    interface IMemento{
    }
    
    class CharacterOriginator{
        private int potion;
        private String position;
        public void move(String place){
            position = place;
        }
        public void usePotion(){
            potion --;
        }
        public int getPotion() {
            return potion;
        }
        private void setPotion(int potion) {
            this.potion = potion;
        }
        public String getPosition() {
            return position;
        }
        private void setPosition(String position) {
            this.position = position;
        }
        public IMemento createMemento(){
            return new Memento(potion, position);
        }
        public void restoreMemento(IMemento memento){
            setPotion(((Memento)memento).getPotion());
            setPosition(((Memento)memento).getPosition());
        }
        public CharacterOriginator(int potion, String position){
            this.potion = potion;
            this.position = position;
        }
        private class Memento implements IMemento{
            private int potion;
            String position;
            public Memento(int potion, String position){
                this.potion = potion;
                this.position = position;
            }
            public int getPotion() {
                return potion;
            }
            public String getPosition() {
                return position;
            }
            
        }
    }
    
    class Caretaker{
        IMemento memento;
        public IMemento getMemento() {
            return memento;
        }
        public void setMemento(IMemento memento) {
            this.memento = memento;
        }
    }
    
    
    class Memento
    {
        public static void main(String[] args) {
            CharacterOriginator player = new CharacterOriginator(10, "世界之石");
            Caretaker caretaker = new Caretaker();
            caretaker.setMemento(player.createMemento());
            System.out.printf("玩家携带的药剂:%d,所在位置:%s
    ", player.getPotion(), player.getPosition());
            player.usePotion();
            player.move("巴尔的宫殿");
            //玩家挑战失败后又一次读档
            System.out.printf("玩家携带的药剂:%d,所在位置:%s
    ", player.getPotion(), player.getPosition());
            player.restoreMemento(caretaker.getMemento());
            System.out.printf("玩家携带的药剂:%d,所在位置:%s
    ", player.getPotion(), player.getPosition());
        }
    

      如今来分析一下上面的代码,并同一时候解说备忘录模式。备忘录模式有3个參与者:Originator——负责创建备忘录、还原备忘录,人物的各种状态都在此,如样例中的CharacterOriginator。Memento——备忘录,它表示须要存储哪些数据,Originator通过须要在备忘录上取数据。在上例中,Memento为Originator的一个内部类。Caretaker——负责保存、获取Memento。为了不暴露Memento的内部方法(我们觉得,Memento的内部方法仅仅能由CharacterOriginator获取),我们让Memento继承了一个空接口IMemento,因此通过Caretaker获得的备忘录均是IMemento类型的,我们无法对它做不论什么事情,可是能够把它传给CharacterOriginator,然后Originator的restoreMemento能够把IMemento类型强制转换为Memento类型。请注意,因为Memento为内部私有类,因此除了CharacterOriginator外,其余的类无法调用Memento的方法,这也就是我们说的“不暴露Memento内部方法”。restoreMemento中清晰写明了应该还原哪些状态,在这里就不进行详解了。

      最后我们看看main方法。首先实例化了一个玩家(player),他有10瓶药水,位于世界之石;随后他进入了巴尔的宫殿,并用掉了一瓶药水;最后,他因为挑战失败而恢复到了曾经的存档点——拥有10瓶药水,位于世界之石。因此,程序执行的结果为:

    玩家携带的药剂:10,所在位置:世界之石

    玩家携带的药剂:9,所在位置:巴尔的宫殿

    玩家携带的药剂:10,所在位置:世界之石

      以上就是备忘录模式的说明,希望能对大家有所帮助。


  • 相关阅读:
    删除购物车列表页面商品
    购物车页面修改数量功能实现
    cookie来实现购物车功能
    wxWidgets学习计划
    正则校验表达式
    Vue组件间的参数传递与Vue的路由实现
    Vue实现数据双向绑定的原理
    Vue的生命周期
    对于mvvm的理解
    vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4244592.html
Copyright © 2011-2022 走看看