A good snapshot stops a beautiful moment from running away. At some point, we’ll press the restore button and relive that moment again.
The memento pattern captures the complete state of an object into a memento that can be used to reset the object at a later date. It allows a complete reset of an object without the need to track and apply individual undo commands. – Design Pattern in Swift
//: Just a sign to show the class / struct is a memento, nothing special
protocol Memento {
}
//: The originator can create and restore game state
protocol Originator {
func createMemento () -> Memento
func applyMemento ( memento : Memento )
}
//: a game state entry
struct GameStateEntry {
var level : Int
var weapon : String
var points : Int
}
//: A GameState memento, which contains all the information the CheckPoint needed to restore the state
struct GameMemento : Memento {
private let entries : [ Int : GameStateEntry ]
private let nextId : Int
private let totalPoints : Int
init ( checkPoint : CheckPoint ){
self . entries = checkPoint . entries
self . nextId = checkPoint . nextId
self . totalPoints = checkPoint . totalPoints
}
func apply ( checkPoint : CheckPoint ) {
print ( "Restoring a game state to a checkpoint..." )
checkPoint . nextId = nextId
checkPoint . totalPoints = totalPoints
checkPoint . entries = entries
}
}
//: A CheckPoint can create and restore game state
class CheckPoint : Originator {
private var entries : [ Int : GameStateEntry ] = [ : ]
private var totalPoints : Int = 0
private var nextId : Int = 0
func addGameStateEntry ( level : Int , weapon : String , points : Int ) {
let entry = GameStateEntry ( level : level , weapon : weapon , points : points )
entries [ nextId ++ ] = entry
totalPoints += points
}
func createMemento () -> Memento {
return GameMemento ( checkPoint : self )
}
func applyMemento ( memento : Memento ) {
guard let m = memento as ? GameMemento else { return }
m . apply ( self )
}
func printCheckPoint () {
print ( "Printing checkPoint...." )
entries . sort { $ 0.0 & lt ; $ 1.0 }
. map {
print ( "Level: \($0.1.level) Weapon: \($0.1.weapon) Points: \($0.1.points) " )
}
print ( "Total Points: \(totalPoints) \n " )
}
}
//:Testing
let checkPoint = CheckPoint ()
checkPoint . addGameStateEntry ( 0 , weapon : "Fire Ball" , points : 20 )
checkPoint . addGameStateEntry ( 1 , weapon : "Flood" , points : 10 )
checkPoint . printCheckPoint ()
let memento = GameMemento ( checkPoint : checkPoint )
checkPoint . addGameStateEntry ( 2 , weapon : "Crusher" , points : 30 )
checkPoint . addGameStateEntry ( 4 , weapon : "Flower" , points : 30 )
checkPoint . printCheckPoint ()
checkPoint . applyMemento ( memento )
checkPoint . printCheckPoint ()