设计模式 行为型模式 – 备忘录模式(定义、结构、优缺点 适用场景分析)
1. 备忘录模式 具体实例:游戏挑战BOSS游戏中的某个场景,一游戏角色有生命力、攻击力、防御力等数据,在打Boss前和后一定会不一样的,我们允许玩家如果感觉与Boss决斗的效果不理想可以让游戏恢复到决斗之前的状态。
要实现上述案例,有两种方式:
- “白箱”备忘录模式
- “黑箱”备忘录模式
1.1 “白箱”备忘录模式(不推荐 破坏封装性)
备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开。类图如下:
代码实现:
GameRole.java
package com.tian.memento.white_box; public class GameRole { private int vit; //生命力 private int atk; //攻击力 private int def; //防御力 //初始化内部状态 public void initState() { this.vit = 100; this.atk = 100; this.def = 100; } //战斗 public void fight() { this.vit = 0; this.atk = 0; this.def = 0; } //保存角色状态功能 public RoleStateMemento saveState() { return new RoleStateMemento(vit, atk, def); } //恢复角色状态 public void recoverState(RoleStateMemento roleStateMemento) { //将备忘录对象中存储的状态赋值给当前对象的成员 this.vit = roleStateMemento.getVit(); this.atk = roleStateMemento.getAtk(); this.def = roleStateMemento.getDef(); } //展示状态功能 public void stateDisplay() { System.out.println("角色生命力:" + vit); System.out.println("角色攻击力:" + atk); System.out.println("角色防御力:" + 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; } }
RoleStateMemento.java
package com.tian.memento.white_box; public class RoleStateMemento { private int vit; //生命力 private int atk; //攻击力 private int def; //防御力 public RoleStateMemento(int vit, int atk, int def) { this.vit = vit; this.atk = atk; this.def = def; } public RoleStateMemento() { } 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; } }
RoleStateCaretaker.java
package com.tian.memento.white_box; public class RoleStateCaretaker { //声明RoleStateMemento类型的变量 private RoleStateMemento roleStateMemento; public RoleStateMemento getRoleStateMemento() { return roleStateMemento; } public void setRoleStateMemento(RoleStateMemento roleStateMemento) { this.roleStateMemento = roleStateMemento; } }
Client.java
package com.tian.memento.white_box; public class Client { public static void main(String[] args) { System.out.println("---------------大战boos前-----------------"); //创建游戏角色对象 GameRole gameRole = new GameRole(); gameRole.initState();//初始化状态 *** 作 gameRole.stateDisplay(); //将该游戏角色内部状态进行备份 //创建管理者对象 RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker(); roleStateCaretaker.setRoleStateMemento(gameRole.saveState()); System.out.println("---------------大战boos后-----------------"); //损耗严重 gameRole.fight(); gameRole.stateDisplay(); System.out.println("---------------恢复之前的状态-----------------"); gameRole.recoverState(roleStateCaretaker.getRoleStateMemento()); gameRole.stateDisplay(); } }
运行结果:
分析:
白箱备忘录模式是破坏封装性的。但是通过程序员自律,同样可以在一定程度上实现模式的大部分用意。
1.2 “黑箱”备忘录模式(推荐)
代码实现:
Memento.java
窄接口 Memento ,这是一个标识接口,因此没有定义出任何的方法
package com.tian.memento.black_box; public interface Memento { }
GameRole.java
定义发起人类 GameRole ,并在内部定义备忘录内部类RoleStateMemento (该内部类设置为私有的)
package com.tian.memento.black_box; public class GameRole { private int vit; //生命力 private int atk; //攻击力 private int def; //防御力 //初始化内部状态 public void initState() { this.vit = 100; this.atk = 100; this.def = 100; } //战斗 public void fight() { this.vit = 0; this.atk = 0; this.def = 0; } //保存角色状态功能 public Memento saveState() { return new RoleStateMemento(vit, atk, def); } //恢复角色状态 public void recoverState(Memento memento) { RoleStateMemento roleStateMemento = (RoleStateMemento) memento; //将备忘录对象中存储的状态赋值给当前对象的成员 this.vit = roleStateMemento.getVit(); this.atk = roleStateMemento.getAtk(); this.def = roleStateMemento.getDef(); } //展示状态功能 public void stateDisplay() { System.out.println("角色生命力:" + vit); System.out.println("角色攻击力:" + atk); System.out.println("角色防御力:" + 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; } private static class RoleStateMemento implements Memento { private int vit; //生命力 private int atk; //攻击力 private int def; //防御力 public RoleStateMemento(int vit, int atk, int def) { this.vit = vit; this.atk = atk; this.def = def; } public RoleStateMemento() { } 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; } } }
RoleStateCaretaker.java
负责人角色类 RoleStateCaretaker 能够得到的备忘录对象是以 Memento 为接口的,由于这个接口仅仅是一个标识接口,因此负责人角色不可能改变这个备忘录对象的内容
package com.tian.memento.black_box; public class RoleStateCaretaker { //声明RoleStateMemento类型的变量 private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }
Client.java
package com.tian.memento.black_box; public class Client { public static void main(String[] args) { System.out.println("---------------大战boos前-----------------"); //创建游戏角色对象 GameRole gameRole = new GameRole(); gameRole.initState();//初始化状态 *** 作 gameRole.stateDisplay(); //将该游戏角色内部状态进行备份 //创建管理者对象 RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker(); roleStateCaretaker.setMemento(gameRole.saveState()); System.out.println("---------------大战boos后-----------------"); //损耗严重 gameRole.fight(); gameRole.stateDisplay(); System.out.println("---------------恢复之前的状态-----------------"); gameRole.recoverState(roleStateCaretaker.getMemento()); gameRole.stateDisplay(); } }
运行结果:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)