2014-12-15 4 views
0

Я попытался реализовать некоторую реализацию Memento pattern в Java.Шаблоны Memento не работают правильно

Пример прост - скопируйте видеоигру в качестве примера, когда пользователь нажимает 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(); 
    } 
} 

Любые предложения?

ответ

1

Проблема заключается в том, что вы повторно один и тот же GameState ссылка на GameMemento объекта. Поэтому, когда вы меняете объект объекта GameState, он также меняет тот, который был сохранен в GameMemento.

Чтобы это исправить, необходимо сохранить копию GameState объекта, а не его исходная ссылка, изменить код, как на примере ниже:

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

Вы также можете использовать метод clone, чтобы скопировать текущий экземпляр GameState.

1

Ваш стек имеет ссылку на тот же объект GameOriginator. Вы сохраняете защитную копию в стеке для последующего ее получения.

public GameMemento saveGame() { 
return new GameMemento(new GameState(gameState.getHealth(), gameState.getKilledMonsters())); 
} 
Смежные вопросы