• [工作中的设计模式]备忘录模式memento


    一、模式解析

      备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。

      备忘录模式可以根据客户指令,将相应的对象特有属性进行快照,如果客户要恢复对象,则根据快照提供的特有属性进行还原。

    二、模式代码

    package memento.patten;
    /**
      *备忘录类,同时指定要保存的对象属性 
     * @author zjl
     * @time 2016-2-1
     * 备忘录:仅有一个状态需要保存
     * @author zjl
     * @time 2016-2-1
     *
     */
    public class Memento {
        private String state;
        public Memento(String state){
            this.state=state;
        }
        public String getState() {
            return state;
        }
        public void setState(String state) {
            this.state = state;
        }
    }

    2、发起者决定备忘录的属性,已经生成备忘录和还原备忘录的方法

    package memento.patten;
    
    public class Originator {
        public String state;
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
        /**
         * 生成备忘录
         * @return
         */
        public Memento createMemento(){
            return new Memento(state);
        }
        public void restoreMemento(Memento memento){
            this.setState(memento.getState());
        }
    
    }

    3、 备忘录保存的类

    package memento.patten;
    
    public class Caretaker {
        private Memento memento;
    
        public Memento getMemento() {
            return memento;
        }
    
        public void setMemento(Memento memento) {
            this.memento = memento;
        }
        
    
    }

    5、客户端调用

    package memento.patten;
    
    public class Client {
        public static void main(String[] args) {
            Originator originator=new Originator();
            originator.setState("状态1");
            System.out.println("初始状态为:"+originator.getState());
            Caretaker caretaker=new Caretaker();
            caretaker.setMemento(originator.createMemento());
            
            originator.setState("状态2");
            System.out.println("当前状态为:"+originator.getState());
            
            //恢复备份
            originator.restoreMemento(caretaker.getMemento());
            System.out.println("恢复后状态为:"+originator.getState());
            
        }
    }

    三、疑问

    以上是备忘录模式的UML图,一直以来的模式均为提供UML图,但是备忘录是个特例,有几个问题需要这里:

    1、发起人需要确定保存哪些信息,并提供保存和还原方法,整个设计模式缺少了对被保存对象的定义所以看起来并不完整
    2、管理角色目前仅提供了备忘录的引用,实际中可能存在多个备忘录的保存,因此需要保存备忘录集合

    所以我们在场景中需要进行完善。

    四、场景

    由于做的大部分项目对于功能节点的保存和还原均使用持久化技术,包括数据库和问题进行保存,因此使用备忘录的模式很少,不过我们仍然可以通过一些常见的场景进行模拟。

    我们进场玩的单机游戏,有如下元素

    游戏界面:人物显示,调取存档指令,还原指令

    人物:游戏角色,有等级、血量、防御、经验的要素,人物有工具,防守,升级的动作

    存档:存档中不需要人物动作,只需要保留基本信息即可

    存档中心:可以保存多个存档

    客户端:客户仅和游戏界面进行打交道

    五、场景代码

    package memento.example;
    
    
    /**
     * 游戏类,
     * 游戏的主界面,主要运行游戏,生成存档以及还原存储
     * 此处省略运行游戏逻辑
     * @author zjl
     * @time 2016-2-1
     *
     */
    public class Game {
        //游戏角色
        public Role role;
        public Role getRole() {
            return role;
        }
        public void setRole(Role role) {
            this.role = role;
        }
        public SaveCenter center=new SaveCenter();
        
        public void createSave(int pos,Role role){
            center.save(pos, new Save(role));
        }
        public void restoreSave(int pos){
            this.role.setLevel(center.getSave(pos).getLevel());
        }
    }

    2、游戏角色

    package memento.example;
    /**
     * 游戏角色,有等级,生命,攻击力,防守力
     * @author zjl
     * @time 2016-2-1
     *
     */
    public class Role {
        private int level;
        private int vit;//生命
        private int atk;//攻击力
        private int def;//防守
        public Role(int level){
            this.setLevel(level);
        }
        
        public void setLevel(int level){
            this.level=level;
            this.vit=level*400;
            this.atk=level*20;
            this.def=level*5;
            
        }
        public int getLevel(){
            return this.level;
        }
    
        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 levelup(){
            setLevel(this.level+1);
        }
    
        @Override
        public String toString() {
            return "Role [level=" + level + ", vit=" + vit + ", atk=" + atk + ", def=" + def + "]";
        }
        
        
    }

    3、游戏存档

    package memento.example;
    /**
     * 游戏存档,保存任务等级,如果有其他信息也可以一并保存
     * @author zjl
     * @time 2016-2-1
     *
     */
    public class Save {
        private int level;
        
        public Save(Role role){
            this.level=role.getLevel();
        }
    
        public int getLevel() {
            return level;
        }
    
        public void setLevel(int level) {
            this.level = level;
        }
        
        
    }

    4、存档中心

    package memento.example;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 存档中心
     * 可以有多个存档,根据位置进行保存
     * @author zjl
     * @time 2016-2-1
     *
     */
    public class SaveCenter {
        public Map<Integer, Save> map=new HashMap<Integer, Save>();
        
        public void save(int pos,Save save){
            map.put(pos, save);
        }
        public Save getSave(int pos){
            return map.get(pos);
        }
    
    }

    5、玩家界面

    package memento.example;
    
    public class Client {
        public static void main(String[] args) {
            Game game=new Game();
            Role lixiaoyao=new Role(1);
            game.setRole(lixiaoyao);
            System.out.println(game.getRole());
            
            game.createSave(1, game.getRole());
            game.getRole().levelup();
            System.out.println(game.getRole());
            game.getRole().levelup();
            System.out.println(game.getRole());
            game.restoreSave(1);
            System.out.println(game.getRole());
            
        }
    }

    6、执行结果

    Role [level=1, vit=400, atk=20, def=5]
    Role [level=2, vit=800, atk=40, def=10]
    Role [level=3, vit=1200, atk=60, def=15]
    Role [level=1, vit=400, atk=20, def=5]
  • 相关阅读:
    CentOS 6.5下安装MySQL 5.6.21
    Java文件实时监控Commons-io
    quartz 实例记录
    Quartz任务调度快速入门(转)
    MySQL日期时间函数大全(转)
    struts2 jsp 传参 NullPointerException问题解决
    hibernate cascade=CascadeType.All
    struts2 学习记录 过滤器 国际化
    struts2 struts1.x 区别
    学习 自己的过滤器和监听器
  • 原文地址:https://www.cnblogs.com/jyyzzjl/p/5182594.html
Copyright © 2020-2023  润新知