0% completed
The Memento Pattern is a type of behavioral design pattern that can be used to save the state of an object so that it can be restored to that state later without breaking the encapsulation. This pattern is beneficial for implementing undo features.
Consider a video game in which players progress through multiple levels and gain multiple items, abilities, achievements, and milestones. The problem arises when the player wants to go back to the previous game state, either to explore the game using some different path or to recover from a mistake made in the game. Manipulating the game's internal state directly to enable this could be complicated and risky, potentially corrupting the game data.
The solution to this problem is hidden in the Memento Pattern. This pattern can save the game state after some time intervals or some milestones. Each memento object represents a game state at a given point in time, as depicted in the image above. Whenever the game player wishes to revert to the previous game state, the game can restore that particular memento object and get that state. Using this approach, we can maintain the integrity of the game's internal structure. Moreover, it simplifies the process of implementing save and load functions.
The class diagram of the Memento Pattern consists of the following key components:
In a video game, players advance through different stages while gathering objects and achieving goals. Players must be able to save their progress in the game and return to it whenever they'd like.
Let's look at the pseudocode for this example:
Class Game { Private level: Integer Private score: Integer Private inventory: List of Items Private gameSaveManager: GameSaveManager Constructor() { gameSaveManager = new GameSaveManager() } Method play(levelIncrement: Integer, scoreIncrement: Integer, newItems: List of Items) { level += levelIncrement score += scoreIncrement inventory.addAll(newItems) gameSaveManager.addSave(createSave()) } Method createSave(): GameSave { return new GameSave(level, score, inventory) } Method loadSave(gameSave: GameSave) { this.level = gameSave.getLevel() this.score = gameSave.getScore() this.inventory = gameSave.getInventory() } Method undoLastPlay() { loadSave(gameSaveManager.getLastSave()) } } Class GameSave { Private level: Integer Private score: Integer Private inventory: List of Items Constructor(level: Integer, score: Integer, inventory: List of Items) { this.level = level this.score = score this.inventory = inventory } Method getLevel(): Integer { return level } Method getScore(): Integer { return score } Method getInventory(): List of Items { return inventory } } Class GameSaveManager { Private saves: Stack of GameSave Method addSave(gameSave: GameSave) { saves.push(gameSave) } Method getLastSave(): GameSave { return saves.pop() } } // Client Code Main { game = new Game() game.play(1, 100, [Item1, Item2]) // Play level 1 game.play(2, 200, [Item3]) // Play level 2 game.undoLastPlay() // Reverts to the state after playing level 1 }
After every play, the Game class's play
method creates a new save and modifies the current state. The game can be returned to its last saved state using the undoLastPlay
method. This method allows players to save their progress and return to previous states without exposing the game's complex state management.
Among the numerous benefits of the Memento Pattern, some of the most common applications of it are:
Pros | Cons |
---|---|
State Preservation: Safely stores states without exposing the originator's internal structure. | Memory Usage: Can consume significant memory if frequent states are saved, especially for complex objects. |
Undo/Redo Functionality: Simplifies the implementation of undo/redo mechanisms. | Complexity: Adds complexity to the code, particularly in managing the lifecycle of mementos. |
High Cohesion: Keeps the state-saving logic within the originator, maintaining high cohesion. | State Recovery Issues: Incorrect implementation can lead to inconsistent state recovery. |
Decoupling: Caretakers and originators are decoupled, leading to cleaner code. | Performance Overhead: Saving and restoring states can be costly in terms of performance, especially for large objects. |
The Memento pattern is a powerful design tool for state preservation and undo functionality, allowing for a clear separation of the state-saving logic from the rest of the application. Although it has many advantages, particularly in terms of user experience and system dependability, it also presents complexity and memory management issues. The Memento pattern has advantages, but utilizing them effectively requires careful implementation and state management.
.....
.....
.....