【设计模式】你知道游戏SL大法是什么设计模式吗?

简介: 【设计模式】你知道游戏SL大法是什么设计模式吗?

什么是备忘录模式

老规矩,我们先来看看备忘录模式 (Memento) 的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

它的UML类图如下:

从上图可以发现,备忘录模式其实整体分为三个部分:Originator(发起人)、备忘录(Memento)、CareTaker(管理者)。其中,Originator负责创建一个备忘录Memento,并哟个memento记录当前时刻它的内部状态

部分或整体) ,同时,也可以使用备忘录Memento恢复到某一个状态;备忘录Memento负责记录、存储发起人Originator的内部状态,并且只有发起人Originator能够访问其内部数据;而管理者Caretaker就负责保存备忘录Memento,注意,它不会查看备忘录里的具体内容。

举一个大家熟知的例子,SL大法知道吧?

在游戏里,当我们保存进度时,玩家角色就是一个发起人,而角色的当前状态(等级、血量、魔法值等)被保存(Save);当我们想重来的时候,读取存档(Load),就能够恢复角色到之前某一个时刻的状态。上述整个过程其实就是备忘录模式的具体体现,接下来我们就以游戏保存、读取来看看备忘录模式的具体应用。

如何使用备忘录模式?

先定义一个英雄类,表示玩家操作的游戏角色,他拥有生命值、魔法值、攻击力、防御力:

  • 英雄类
@Data
public class Hero {
    private int hp;
    private int mp;
    private int atk;
    private int def;

    // 初始角色状态
    public void getInitialState() {
        this.hp = 100;
        this.mp = 50;
        this.atk = 10;
        this.def = 5;
    }

    // 当前状态展示
    public void displayState() {
        System.out.println("角色当前状态:");
        System.out.println("生命值:" + this.hp);
        System.out.println("魔法值:" + this.hp);
        System.out.println("攻击力:" + this.atk);
        System.out.println("防御力: " + this.def);
        System.out.println("******************");
    }

    // 角色经验升级,恢复一定生命、魔法并增加属性
    public void levelUp() {
        this.hp += 20;
        this.mp += 10;
        this.atk += 5;
        this.def += 5;
    }

    // 大战boss
    public void fight() {
        this.hp -= 99;
        this.mp -= 50;
    }

    // 保存现在状态
    public SavaMemento saveState() {
        return (new SavaMemento(hp, mp, atk, def));
    }

    // 恢复之前状态
    public void loadState(SavaMemento memento) {
        this.hp = memento.getHp();
        this.mp = memento.getMp();
        this.atk = memento.getAtk();
        this.atk = memento.getDef();
    }
}

我们注意到,英雄类里除了初始化、战斗等函数,有两个公共方法:SaveMemento和loadState,前者返回了一个存档,后者则根据这个存档恢复到某一个时刻的状态。其实也可以这么理解,保存存档的时候,得到了一个存档id,之后读取存档则需要该存档id。

  • 存档类

存档类的实现很简单,就是根据最初系统的设计目的,来保存对应的英雄类中的某些信息。

public class SavaMemento {
    private int hp; // 生命力
    private int mp; // 魔法值
    private int atk; // 攻击力
    private int def; // 防御力

    public SavaMemento(int hp, int mp, int atk, int def) {
        this.hp = hp;
        this.mp = hp;
        this.atk = atk;
        this.def = def;

    }
}
  • 存档保管箱

存档保存角色信息,而存档保管箱则是将存档的实现细节收敛,防止客户端知道其具体的实现细节。

public class CareTaker {

    private SavaMemento savaLoadMemento;

    public SavaMemento loadGame() {
        try {
            if (savaLoadMemento != null)
                return savaLoadMemento;
            else
                throw new Exception();
        } catch (Exception ignored) {
            System.out.println("The saveFile is missed!");
        }
        return new SavaMemento(100, 50, 10, 5);
    }

    public void saveGame(SavaMemento memento) {
        this.savaLoadMemento = memento;
    }
}
  • 游戏客户端

设计一个游戏客户端,操作一个游戏角色从出生到大战boss、再到读取存档的过程:

public class GameClient {

    public static void main(String[] args) {

        // 显示初始状态
        System.out.println("初始状态--");
        Hero hero = new Hero();
        hero.getInitialState();
        hero.displayState();

        // 保存游戏
        System.out.println("保存游戏--");
        CareTaker caretaker = new CareTaker();
        caretaker.saveGame(hero.saveState());

        // 打死大boss
        System.out.println("三拳打死Boss--");
        hero.fight();
        hero.displayState();

        // 升级啦
        System.out.println("经验升级--");
        hero.levelUp();
        hero.displayState();

        // 恢复游戏
        System.out.println("读取存档--");
        hero.loadState(caretaker.loadGame());
        hero.displayState();
    }
}
  • 来看看输出

总结

应用场景

备忘录模式主要应用在这样的场景:需要记录某一个对象的内部状态,并且能够将对象恢复到某一个时刻状态,例如用户操作redo、或者游戏进度保存等等。

优点

提供了一种可以恢复状态的机制,进行回溯甚至将对象恢复到任意时刻的状态。

缺点

会额外消耗资源,因为需要将对象的状态信息进行保存,不过这个缺点在实际业务场景下都是可以接受的。

参考资料

《大话设计模式》

相关文章
|
8月前
|
设计模式 uml
【设计模式】建造者模式就是游戏模式吗?
【设计模式】建造者模式就是游戏模式吗?
42 0
|
设计模式 资源调度 Java
基于java平台和运用5种设计模式的五子棋游戏
基于java平台和运用5种设计模式的五子棋游戏
281 0
基于java平台和运用5种设计模式的五子棋游戏
|
4天前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
4月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
2月前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
2月前
|
设计模式 安全 Java
Kotlin - 改良设计模式 - 构建者模式
Kotlin - 改良设计模式 - 构建者模式
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
46 1
|
3月前
|
设计模式 Java Kotlin
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。对于快速学习Kotlin语法,推荐查看“简洁”系列教程。本文重点介绍了构建者模式在Kotlin中的应用与改良,包括如何使用具名可选参数简化复杂对象的创建过程,以及如何在初始化代码块中对参数进行约束和校验。
34 3
|
4月前
|
设计模式 算法 安全
设计模式——模板模式
模板方法模式、钩子方法、Spring源码AbstractApplicationContext类用到的模板方法
设计模式——模板模式