GoF의 디자인 패턴, 메멘토 패턴에 대해 알아본다.
해당 글은, 다음의 코드를 기반으로 이해하는 것이 편리합니다.
//
// Walker.swift
// Memento
//
// Created by Choiwansik on 2023/02/07.
//
import Foundation
internal class Walker {
internal init(current: Coordinate, target: Coordinate) {
self.current = current
self.target = target
}
internal func walk(with action: String) {
self.actionList.append(action)
if action == "UP" {
self.current.addY(diff: +1)
} else if action == "RIGHT" {
self.current.addX(diff: +1)
} else if action == "DOWN" {
self.current.addY(diff: -1)
} else if action == "LEFT" {
self.current.addX(diff: -1)
}
}
internal func createMemento() -> Memento {
Memento(coordinate: self.current, actionList: self.actionList)
}
internal func restore(with memento: Memento) {
self.current = memento.coordinate
self.actionList = memento.actionList
}
internal var remainingDistance: Double {
let xSquare = pow(Double((self.current.x - self.target.x)), 2.0)
let ySquare = pow(Double((self.current.y - self.target.y)), 2.0)
return sqrt(Double(xSquare) + Double(ySquare))
}
internal var description: String {
self.actionList.map { "\($0)" }.joined(separator: " ")
}
private var current: Coordinate
private let target: Coordinate
private var actionList = Array<String>()
}
extension Walker {
internal class Memento {
internal init(coordinate: Coordinate, actionList: Array<String>) {
self.coordinate = coordinate
self.actionList = actionList
}
internal let coordinate: Coordinate
internal let actionList: Array<String>
}
}
internal struct Coordinate {
private(set) var x: Int
private(set) var y: Int
internal mutating func addX(diff: Int) {
self.x += diff
}
internal mutating func addY(diff: Int) {
self.y += diff
}
}
//
// main.swift
// Memento
//
// Created by Choiwansik on 2023/02/07.
//
import Foundation
internal func main() {
let start = Coordinate(x: 0, y: 0)
let destination = Coordinate(x: 10, y: 10)
let walker = Walker(current: start, target: destination)
let actions = ["UP", "RIGHT", "DOWN", "LEFT"]
var minDistance = Double.greatestFiniteMagnitude
var memento: Walker.Memento?
while true {
let action = actions[Int.random(in: 0..<actions.count)]
walker.walk(with: action)
let remainDistance = walker.remainingDistance
print(remainDistance)
if remainDistance == .zero {
break
}
// 거리가 작아지면 저장함
if minDistance > remainDistance {
minDistance = remainDistance
memento = walker.createMemento()
// 거리가 커지는 경우 이전 상태를 불러옴
} else if let memento {
walker.restore(with: memento)
}
}
print("walker's path: \(walker.description)")
}
main()
main
)는 이 객체를 만들고 관리하는데 필요한 비용을 알 수 없다.NSCoding
)