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(); } }
- 此时运行后控制台为:
玩家玩到第三局的时候,就失败了。同样多测试几次后也类似,少有的一路顺风直到最后的。可见,这个游戏是有难度的,那么我们怎么去百分百的成功呢。
假设我们设置,在游戏开始前,设置一个快照,保存游戏进度,当游戏开始后,赢了的话,就更新进度,输了的话,就重新开始当前的关卡。
- 我们设置了一个快照类,用于保存进度的
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(); } }
- 此时控制台输出就变成了:
当闯关失败时候,就恢复到快照,成功就继续闯关。这样一来,基本上就是百试不爽的,次次成功了。哈哈哈!!!