前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >看完,你也能用备忘录模式手写一个游戏的存档功能!

看完,你也能用备忘录模式手写一个游戏的存档功能!

作者头像
程序视点
发布2023-09-13 12:35:45
2580
发布2023-09-13 12:35:45
举报
文章被收录于专栏:程序小小事
今天和大家聊一聊备忘录模式(Memento Design Pattern)

简介

还是把这张概总图放这里。

备忘录模式,也叫快照(Snapshot)模式,英文翻译是Memento Design Pattern。在 GoF 的《设计模式》一书中,备忘录模式是这么定义的:

Captures and externalizes an object’s internal state so that it can be restored later, all without violating encapsulation.

翻译成中文就是:在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。

概念性的东西,表述得很正确,但如果不懂的,依旧不明白它在说什么。

举个例子给大家分享下:

游戏中的存档功能就是备忘录模式。我们在玩游戏时,到一定的进度时,我们觉得当前的状态就是最有利的,因此我们会调用存档的功能,把当前的状态存储到某个地方或者某个文件中。当我们后续的某个操作出现问题时,再读取存档就能回到我们刚才保存的进度。

示例解析

就刚才的例子。我们把整个游戏看做一个对象:Game。在这个游戏中,我们的进度,就是描述的当前游戏的状态,比如我们赚取的金布数量。因此,在 Game 中始终有一个金币数量的状态:money。

现在,我们想要把这个金币的数量进行存档。在游戏中,是不是经常有一个存档的功能?这就对应着:Game中有一个存档的功能方法。同样,我们进行读档的时候,对应着的就是 Game 中读档的功能方法。

存档或读档的数据也是游戏的一种状态。我们不会把这个存档的状态和 Game 中现有的状态混在一起。因为在读档的时候,存档中的状态会覆盖 Game 中原有的状态。因此,我们需要一个独立的对象来表示这个存档状态(为什么用对象呢?因为我们的状态可能不止金币,可能还有装备,或者其他的):Memento。

目前,我们已经提到了备忘录中的两个角色了:发起者角色(Game)和备忘录角色(Memento)。

注意,这里还有一个角色:备忘录管理者角色。它用来管理备忘录,仅提供备忘录的存储和获取。为什么呢?因为你的备忘录可能不止一个,就像你的存档不止一个一样。

🆗,让我们简单的实现下这个例子。

示例代码

首先时发起者角色:Game 类。

代码语言:javascript
复制
public class Gamer {
    
    private int money;
    
    public int getMoney(){
        return money;
    }
    
    public Gamer(int money){
        this.money=money;
    }
    
    public Memento createMemento(){
        Memento m=new Memento(money);
        Iterator it=fruits.iterator();
        while(it.hasNext()){
            String fruit=(String)it.next();
            if(fruit.startsWith("好吃的")){
                m.addFruits(fruit);
            }
        }
        return m;
    }
    
    public  void restoreMemento(Memento memento){
        this.money=memento.getMoney();
        this.fruits=memento.getFruits();
    }
    
    public String toString(){
        return "Money:"+money+" ,Fruits:"+fruits;
    }
    
}

接着,增加存档和读档的方法:createMemento() 和 restoreMemento()

代码语言:javascript
复制
public class Gamer {
    
    private int money;
    
    public void setMoney(int money) {
      this.money = money;
    }
    
    public int getMoney(){
        return money;
    }
    
    public Gamer(){
    
    }
    
    public Gamer(int money){
        this.money=money;
    }
    
    public Memento createMemento(){
        Memento m=new Memento(money);
        return m;
    }
    
    public  void restoreMemento(Memento memento){
        this.money=memento.getMoney();
    }
    
    public String toString(){
        return "Money:"+money;
    }
    
}

在存取档中,用到了备忘录对象:Memento

代码语言:javascript
复制

public class Memento {
    
    private int money;
    
    Memento(int money){
        this.money=money;
    }   
    public int getMoney(){
        return money;
    }
}

注意:备忘录中没有setter方法。为什么呢?大家想一想!*

还有一个类就是备忘录管理者类:MementoManager.

代码语言:javascript
复制
public class MementoManager {
  private List<Memento> mementoList = new ArrayList<>();
  public void add(Memento memento) {
    mementoList.add(memento);
  }
  public Memento get(int index) {
    return mementoList.get(index);
  }
}

让我们来测试一把。

代码语言:javascript
复制
public class GameTest {
  public static void main(String[] args) {
    Game game = new Game();
    MementoManager mementoManager = new MementoManager();
    game.setMoney(100);
    System.out.println("当前的金币是:" + game.getMoney());
    mementoManager.add(game.createMemento());
    
    // 不小心金币损失到只有10了!
    game.setMoney(10);
    System.out.println("当前的金币是:" + game.getMoney());
    
    //从MementoManager取出第一个Memento对象,并给Game赋值回去。(简称:读档)
    game.restoreMemento(mementoManager.get(0));
    System.out.println("执行读档后,当前的金币是:" + game.getMoney());
  }
}

看下结果:当前的金币是:100当前的金币是:10。执行读档后,当前的金币是:100。

我们的金币数量,通过读档后,又回到了起初的100。

这就是备忘录的使用。

总结

备忘录模式是一种简单而有效的数据保存与恢复方法。它通过发起者和备忘录之间的协作,实现了对象状态的临时保存与恢复。

优点:

  • 简单易懂:备忘录模式的实现相对简单,不需要复杂的算法和数据结构。
  • 良好的封装性:备忘录模式能够保持对象的封装性,让客户端无需关心对象的状态保存与恢复的细节。
  • 可扩展性:备忘录模式可以灵活地扩展,支持保存与恢复多个状态,同时也支持撤销操作。

缺点: 如果备忘录对象特别多,那你的备忘录管理者就要存储下所有的对象。这就会消耗大量的内存资源。

因此,在实践中,备忘录管理者都会限制备忘录的数量。也就是我们游戏中,存档的位置是有限制的,有的可以存16个存档,有的可以存32个存档。

备忘录模式在实践中的其他用途

  • 文字处理软件中的撤销功能:用户编辑文本时,可以通过备忘录模式将每一次修改的状态保存下来,以便用户随时撤销到之前的某个状态。
  • 系统故障恢复:系统在运行过程中遇到故障,可以使用备忘录模式将关键状态保存下来,以便在系统恢复后重新加载状态。 ...

大家还想到了哪些应用场景呢?欢迎留言!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-25 08:08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序视点 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 示例解析
  • 示例代码
  • 总结
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档