0

Memento パターンの実装をJava で実装しようとしました。

例は簡単です - 例としてビデオゲームをコピーし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

しかし、最後の 2 行は次のようになっているはずなので、これは間違った結果です。

Health:           90
Killed Monsters:   2

何が悪いのかわかりませんでした。コードは問題ないようです。

コード スニペットは次のとおりです。

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();
    }
}

助言がありますか?

4

2 に答える 2

1

問題は、オブジェクトで同じGameState参照を再利用していることです。GameMementoそのため、オブジェクトのプロパティGameStateを変更すると、 に保存されたものも変更されGameMementoます。

これを修正するには、元の参照ではなくオブジェクトのコピーを保存する必要がありGameStateます。以下の例のようにコードを変更してください。

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

cloneメソッドを使用して、 の現在のインスタンスをコピーすることもできますGameState

于 2014-12-15T13:02:28.097 に答える
1

あなたのスタックは、同じ GameOriginator オブジェクトへの参照を持っています。後で取得するために、防御コピーをスタックに保存します。

public GameMemento saveGame() {
 return new GameMemento(new GameState(gameState.getHealth(), gameState.getKilledMonsters()));
}
于 2014-12-15T13:02:47.373 に答える