【问题标题】:Memento patterns doesn't work correctly纪念品模式无法正常工作
【发布时间】:2023-03-16 01:46:01
【问题描述】:

我尝试在 Java 中实现Memento pattern 的一些实现。

示例很简单 - 以复制视频游戏为例,当用户按下 F5 保存玩家状态 => 按下 F9 后恢复上次保存的玩家状态。

这是轻松运行的输出:

Health:          100
Killed Monsters:   0
Health:           90
Killed Monsters:   2
Health:           81
Killed Monsters:   4
Health:           72
Killed Monsters:   6
Health:           64
Killed Monsters:   8
Health:           57
Killed Monsters:  10

但这是错误的结果,因为最后两行应该是:

Health:           90
Killed Monsters:   2

我不知道出了什么问题。代码看起来不错。

这里是代码sn-p:

import java.util.Stack;

class GameState {
    private int health;
    private int killedMonsters;

    public GameState(int health, int killedMonsters) {
        this.health = health;
        this.killedMonsters = killedMonsters;
    }

    public double getHealth() {
        return health;
    }

    public int getKilledMonsters() {
        return killedMonsters;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public void setKilledMonsters(int killedMonsters) {
        this.killedMonsters = killedMonsters;
    }

    @Override
    public String toString() {
        return  String.format("Health: %1$12d\nKilled Monsters: %2$3d", health, killedMonsters);
    }
}

class GameMemento {
    private GameState gameState;

    public GameMemento(GameState gameState) {
        this.gameState = gameState;
    }

    public GameState getGameState() {
        return gameState;
    }
}

class GameOriginator {
    private GameState gameState = new GameState(100, 0);

    public void play() {
        System.out.println(gameState.toString());
        gameState.setHealth((int)(gameState.getHealth() * 0.9));
        gameState.setKilledMonsters(gameState.getKilledMonsters() + 2);
    }

    public GameMemento saveGame() {
        return new GameMemento(gameState);
    }

    public void loadGame(GameMemento memento) {
        gameState = memento.getGameState();
    }
}

class Caretacker {
    private GameOriginator game = new GameOriginator();
    private Stack<GameMemento> quickSaves = new Stack<>();

    public void shutThisDumbAss() {
        game.play();
    }

    public void F5() {
        quickSaves.push(game.saveGame());
    }

    public void F9() {
        game.loadGame(quickSaves.peek());
    }
}

public class MementoDemo {
    public static void main(String[] args) {
        Caretacker caretacker = new Caretacker();
        caretacker.F5();
        caretacker.shutThisDumbAss();
        caretacker.F5();
        caretacker.shutThisDumbAss();
        caretacker.shutThisDumbAss();
        caretacker.shutThisDumbAss();
        caretacker.shutThisDumbAss();
        caretacker.F9();
        caretacker.shutThisDumbAss();
    }
}

有什么建议吗?

【问题讨论】:

    标签: java design-patterns memento


    【解决方案1】:

    问题是您在 GameMemento 对象中重用了相同的 GameState 引用。因此,当您更改 GameState 对象的 属性 时,它也会更改保存在 GameMemento 中的那个。

    要解决此问题,需要保存 GameState 对象的副本而不是其原始引用,请按照以下示例更改您的代码:

    public GameMemento saveGame() {
         return new GameMemento(new GameState(gameState.getHealth(), gameState.getKilledMonsters()));
    }
    

    您还可以使用clone 方法复制GameState 的当前实例。

    【讨论】:

      【解决方案2】:

      您的堆栈引用了相同的 GameOriginator 对象。您将防御性副本保存在堆栈中以供以后检索。

      public GameMemento saveGame() {
       return new GameMemento(new GameState(gameState.getHealth(), gameState.getKilledMonsters()));
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-23
        • 2018-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多