zoukankan      html  css  js  c++  java
  • 设计模式之——Memento模式

    Memento模式即快照模式,就是在某一时刻,设定一个状态,在后面随时可以返回到当前状态的模式。

    我们拿一个闯关游戏作为举例,一共有十关,每闯一关,玩家所持金额增加一百,而闯关失败就扣一百。初始时,给玩家一百块作为闯关资金,如果十关全部闯玩,并且玩家手中金额不小于0,则胜利,当玩家所持金额小于0,则视为闯关失败,直接退出。

    下面看案例代码,有一个玩家类

    • gamer
    package site.wangxin520.gof.memento.demo.game;
    
    import java.util.Random;
    
    /**
     * 游戏的类
     * @author wangXgnaw
     *
     */
    public class Gamer {
    
        /**
         * 玩家所持有的金钱
         */
        private int money;
        private Random random = new Random();
    
        /**
         * 创建玩家,设置初始化money
         * @param money
         */
        public Gamer(int money) {
            this.money = money;
        }
    
        /**
         * 获取玩家当前所持有的金钱
         * @return
         */
        public int getMoney() {
            return money;
        }
    
        /**
         * 玩游戏的方法
         */
        public void play(){
            
            //要么闯关成功
            if(random.nextBoolean()){
                System.out.println("闯关成功,加一百块");
                this.money+=100;
            }else{
                System.out.println("闯关失败,扣两百块");
                this.money-=200;
            }
            
        }
        
        
        @Override
        public String toString() {
            return "玩家当前有现金: [money=" + money + "]";
        }
        
    }
    • test测试类
    package site.wangxin520.gof.memento.demo;
    
    import site.wangxin520.gof.memento.demo.game.Gamer;
    
    /**
     * 快照模式的一个测试类
     * @author wangXgnaw
     *
     */
    public class Test {
    
        public static void main(String[] args) {
            Gamer gamer = new Gamer(100);
    
            System.out.println("初始时候,玩家状态为:"+gamer);
            
            //玩十局游戏
            for (int i = 0; i < 10; i++) {
    
                gamer.play();
                
                System.out.println("第"+(i+1)+"局的时候,玩家状态为:"+gamer);
                
                //判断游戏结束
                if(gamer.getMoney()<0){
                    System.out.println("玩家失败");
                    break;
                }
            }
            System.out.println();
    
        }
    
    }
    • 此时运行后控制台为:

    image

    玩家玩到第三局的时候,就失败了。同样多测试几次后也类似,少有的一路顺风直到最后的。可见,这个游戏是有难度的,那么我们怎么去百分百的成功呢。

    假设我们设置,在游戏开始前,设置一个快照,保存游戏进度,当游戏开始后,赢了的话,就更新进度,输了的话,就重新开始当前的关卡。

    • 我们设置了一个快照类,用于保存进度的
    package site.wangxin520.gof.memento.demo.game;
    
    /**
     * 游戏的快照的类,当需要爆粗的时候,保存一下进度,用于快速恢复!
     * @author wangXgnaw
     *
     */
    public class Memento {
    
        //保存游戏里面的钱
        private int money;
    
        /**
         * 构造函数,创建一个快照
         * 限定为只能本包中调用
         */
        Memento(int money) {
            this.money=money;
        }
        
        /**
         * 获取快照保存的钱,这里方法的权限为本包中
         * @return
         */
        int getMoney() {
            return money;
        }
    }
    • 修改一下玩家类
    package site.wangxin520.gof.memento.demo.game;
    
    import java.util.Random;
    
    /**
     * 游戏的类
     * @author wangXgnaw
     *
     */
    public class Gamer {
    
        /**
         * 玩家所持有的金钱
         */
        private int money;
        private Random random = new Random();
    
        /**
         * 创建玩家,设置初始化money
         * @param money
         */
        public Gamer(int money) {
            this.money = money;
        }
    
        /**
         * 获取玩家当前所持有的金钱
         * @return
         */
        public int getMoney() {
            return money;
        }
    
        /**
         * 玩游戏的方法
         */
        public void play(){
            
            //要么闯关成功
            if(random.nextBoolean()){
                System.out.println("闯关成功,加一百块");
                this.money+=100;
            }else{
                System.out.println("闯关失败,扣两百块");
                this.money-=200;
            }
            
        }
        
        /**
         * 创建快照,当前的所持的金额
         * @return Memento 返回一个快照
         */
        public Memento createMemento(){
            return new Memento(this.money);
        }
        
        /**
         * 回退到快照
         * @param memento
         */
        public void restoreMemento(Memento memento){
            this.money=memento.getMoney();
        }
        
        /**
         * 查看快照里面的钱
         * @return
         */
        public int getMementoState(Memento memento){
            return memento.getMoney();
        }
    
        @Override
        public String toString() {
            return "玩家当前有现金: [money=" + money + "]";
        }
        
    }
    • 测试类也修改了一下,当成功,就更新进度,当不成功,就回退
    package site.wangxin520.gof.memento.demo;
    
    import site.wangxin520.gof.memento.demo.game.Gamer;
    import site.wangxin520.gof.memento.demo.game.Memento;
    
    /**
     * 快照模式的一个测试类
     * @author wangXgnaw
     *
     */
    public class Test {
    
        public static void main(String[] args) {
            Gamer gamer = new Gamer(100);
    
            System.out.println("初始时候,玩家状态为:"+gamer);
            
            //设置一个快照
            Memento memento=gamer.createMemento();
            
            //玩十局游戏
            for (int i = 0; i < 10; i++) {
    
                gamer.play();
                
                //当钱减少后,就说明了玩家本局闯关失败,那么就回退回去
                if(gamer.getMoney()<gamer.getMementoState(memento)){
                    gamer.restoreMemento(memento);
                    //并且,本局重新来过!
                    i--;
                }else{
                    //本次闯关成功,更新快照
                    memento=gamer.createMemento();
                }
                
                System.out.println("第"+(i+1)+"局的时候,玩家状态为:"+gamer);
                
                //判断游戏结束
                if(gamer.getMoney()<0){
                    System.out.println("玩家失败");
                    break;
                }
            }
            System.out.println();
    
        }
    
    }
    • 此时控制台输出就变成了:

    image

    当闯关失败时候,就恢复到快照,成功就继续闯关。这样一来,基本上就是百试不爽的,次次成功了。哈哈哈!!!

  • 相关阅读:
    Redis --> Redis架构设计
    Redis --> 为redis分配新的端口
    大数据 --> CAP原理和最终一致性
    大数据 --> 一致性Hash算法
    大数据 --> 分布式服务框架Zookeeper
    网络通信 --> Linux 五种IO模型
    网络通信 --> 同步、异步、阻塞与非阻塞介绍
    网络通信 --> Socket、TCP/IP、HTTP、FTP及网络编程
    SoC总线专题
    RISC-V评估系列
  • 原文地址:https://www.cnblogs.com/wangxinblog/p/7734998.html
Copyright © 2011-2022 走看看