打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
简说设计模式——备忘录模式

一、什么是备忘录模式

  备忘录这个词汇大家应该都不陌生,我就经常使用备忘录来记录一些比较重要的或者容易遗忘的信息,与之相关的最常见的应用有许多,比如游戏存档,我们玩游戏的时候肯定有存档功能,旨在下一次登录游戏时可以从上次退出的地方继续游戏,或者对复活点进行存档,如果挂掉了则可以读取复活点的存档信息重新开始。与之相类似的就是数据库的事务回滚,或者重做日志redo log等。

  备忘录模式(Memento),在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存着这个状态。这样以后就可将该对象恢复到原先保存的状态。UML结构图如下:

  其中,Originator是发起人,负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态;Memento是备忘录,负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento;Caretaker是管理者,负责保存好备忘录的Memento,不能对备忘录的内容进行操作或检查。

  1. 发起人角色

  记录当前时刻的内部状态,并负责创建和恢复备忘录数据,允许访问返回到先前状态所需的所有数据。

 1 public class Originator { 2      3     private String state; 4  5     public String getState() { 6         return state; 7     } 8  9     public void setState(String state) {10         this.state = state;11     }12     13     public Memento createMento() {14         return (new Memento(state));15     }16     17     public void setMemento(Memento memento) {18         state = memento.getState();19     }20     21     public void show() {22         System.out.println("state = " + state);23     }24     25 }

  2. 备忘录角色

  负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。

 1 public class Memento { 2      3     private String state; 4      5     public Memento(String state) { 6         this.state = state; 7     } 8      9     public String getState() {10         return state;11     }12 13 }

  3. 备忘录管理员角色

  对备忘录进行管理、保存和提供备忘录,只能将备忘录传递给其他角色。

 1 public class Caretaker { 2      3     private Memento memento; 4  5     public Memento getMemento() { 6         return memento; 7     } 8  9     public void setMemento(Memento memento) {10         this.memento = memento;11     }12     13 }

  4. Client客户端

  下面编写一小段代码测试一下,即先将状态置为On,保存后再将状态置为Off,然后通过备忘录管理员角色恢复初始状态。

 1 public class Client { 2      3     public static void main(String[] args) { 4         Originator originator = new Originator(); 5         originator.setState("On");    //Originator初始状态 6         originator.show(); 7          8         Caretaker caretaker = new Caretaker(); 9         caretaker.setMemento(originator.createMento());10         11         originator.setState("Off");    //Originator状态变为Off12         originator.show();13         14         originator.setMemento(caretaker.getMemento());    //回复初始状态15         originator.show();16     }17 18 }

  运行结果如下:

  

二、备忘录模式的应用

  1. 何时使用

  • 需要记录一个对象的内部状态时,为了允许用户取消不确定或者错误的操作,能够恢复到原先的状态

  2. 方法

  • 通过一个备忘录类专门存储对象状态

  3. 优点

  • 给用户提供了一种可以恢复状态的机制,可以使用能够比较方便地回到某个历史的状态

  • 实现了信息的封装,使得用户不需要关心状态的保存细节

  4. 缺点

  • 消耗资源

  5. 使用场景

  • 需要保存和恢复数据的相关场景

  • 提供一个可回滚的操作,如ctrl+z、浏览器回退按钮、Backspace键等

  • 需要监控的副本场景

  6. 应用实例

  • 游戏存档

  • ctrl+z键、浏览器回退键等(撤销/还原)

  • 棋盘类游戏的悔棋

  • 数据库事务的回滚

  7. 注意事项

  • 为了符合迪米特法则,需要有一个管理备忘录的类

  • 不要在频繁建立备份的场景中使用备忘录模式。为了节约内存,可使用原型模式+备忘录模式

三、备忘录模式的实现

  下面以游戏存档为例,看一下如何用备忘录模式实现。UML图如下:

  1. 游戏角色

  简单记录了游戏角色的生命力、攻击力、防御力,通过saveState()方法来保存当前状态,通过recoveryState()方法来恢复角色状态。

 1 public class GameRole { 2      3     private int vit;    //生命力 4     private int atk;    //攻击力 5     private int def;    //防御力 6      7     public int getVit() { 8         return vit; 9     }10     public void setVit(int vit) {11         this.vit = vit;12     }13     public int getAtk() {14         return atk;15     }16     public void setAtk(int atk) {17         this.atk = atk;18     }19     public int getDef() {20         return def;21     }22     public void setDef(int def) {23         this.def = def;24     }25     26     //状态显示27     public void stateDisplay() {28         System.out.println("角色当前状态:");29         System.out.println("体力:" + this.vit);30         System.out.println("攻击力:" + this.atk);31         System.out.println("防御力: " + this.def);32         System.out.println("-----------------");33     }34     35     //获得初始状态36     public void getInitState() {37         this.vit = 100;38         this.atk = 100;39         this.def = 100;40     }41     42     //战斗后43     public void fight() {44         this.vit = 0;45         this.atk = 0;46         this.def = 0;47     }48     49     //保存角色状态50     public RoleStateMemento saveState() {51         return (new RoleStateMemento(vit, atk, def));52     }53     54     //恢复角色状态55     public void recoveryState(RoleStateMemento memento) {56         this.vit = memento.getVit();57         this.atk = memento.getAtk();58         this.def = memento.getDef();59     }60 61 }

  2. 角色状态存储箱

  备忘录类,用于存储角色状态。

 1 public class RoleStateMemento { 2      3     private int vit;    //生命力 4     private int atk;    //攻击力 5     private int def;    //防御力 6      7     public RoleStateMemento(int vit, int atk, int def) { 8         this.vit = vit; 9         this.atk = atk;10         this.def = def;11     }12 13     public int getVit() {14         return vit;15     }16 17     public void setVit(int vit) {18         this.vit = vit;19     }20 21     public int getAtk() {22         return atk;23     }24 25     public void setAtk(int atk) {26         this.atk = atk;27     }28 29     public int getDef() {30         return def;31     }32 33     public void setDef(int def) {34         this.def = def;35     }36     37 }

  3. 角色状态管理者

  备忘录管理者。

 1 public class RoleStateCaretaker { 2      3     private RoleStateMemento memento; 4  5     public RoleStateMemento getMemento() { 6         return memento; 7     } 8  9     public void setMemento(RoleStateMemento memento) {10         this.memento = memento;11     }12 13 }

  4. Client客户端

  下面编写一个简单的程序测试一下,编写逻辑大致为打boss前存档,打boss失败了,读档。

 1 public class Client { 2      3     public static void main(String[] args) { 4         //打boss前 5         GameRole gameRole = new GameRole(); 6         gameRole.getInitState(); 7         gameRole.stateDisplay(); 8          9         //保存进度10         RoleStateCaretaker caretaker = new RoleStateCaretaker();11         caretaker.setMemento(gameRole.saveState());12         13         //打boss失败14         gameRole.fight();15         gameRole.stateDisplay();16         17         //恢复状态18         gameRole.recoveryState(caretaker.getMemento());19         gameRole.stateDisplay();20     }21 22 }

  运行结果如下:

  

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
图解Java设计模式之备忘录模式
备忘录模式(Memento pattern)
备忘录模式(memento)解析例子
设计模式之备忘录(Memento Pattern)模式
备忘录模式
设计模式读书笔记-----备忘录模式
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服