GoF์˜ ๋””์ž์ธ ํŒจํ„ด, ๋ฉ”๋ฉ˜ํ†  ํŒจํ„ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

ํ•ด๋‹น ๊ธ€์€, ๋‹ค์Œ์˜ ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ์š”์•ฝ

  • ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๊ธฐ์–ตํ•ด๋‘์—ˆ๋‹ค๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ธฐ์–ตํ•ด๋‘” ์ƒํƒœ๋กœ ๊ฐ์ฒด๋ฅผ ๋˜๋Œ๋ฆฐ๋‹ค.
  • ๊ฐ์ฒด์— ์ƒํƒœ์— ๋Œ€ํ•œ ๊ธฐ์–ต์€ ๋‹ค๋ฅธ ๊ฐ์ฒด์—์„œ๋„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์ ‘๊ทผ
  • ๊ฐ์ฒด์˜ ์ƒํƒœ์— ๋Œ€ํ•œ ๊ธฐ์–ต ์ƒ์„ฑ์€ ์˜ค์ง ํ•ด๋‹น ๊ฐ์ฒด๋งŒ์ด ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด์˜ ์Šค๋ƒ…์ƒท์„ ์ €์žฅํ•ด๋‘๋Š” ํŒจํ„ด

์˜ˆ์‹œ

Code

Walker

//
//  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

//
//  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()

ํ™œ์šฉ์„ฑ

  • ์–ด๋–ค ๊ฐ์ฒด์˜ ์ƒํƒœ์— ๋Œ€ํ•œ ์Šค๋ƒ…์ƒท์„ ์ €์žฅํ•œ ํ›„ ๋‚˜์ค‘์— ์ด ์ƒํƒœ๋กœ ๋ณต๊ตฌํ•ด์•ผ ํ•  ๋•Œ
  • ์ƒํƒœ๋ฅผ ์–ป๋Š”๋ฐ ํ•„์š”ํ•œ ์ง์ ‘์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‘๋ฉด ๊ทธ ๊ฐ์ฒด์˜๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์ด ๋“œ๋Ÿฌ๋‚˜๋Š” ๊ฒฝ์šฐ
    • ์บก์Šํ™”๊ฐ€ ๊นจ์ง

๊ฒฐ๊ณผ

  • ์บก์Šํ™”๋œ ๊ฒฝ๊ณ„๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๊ฒฐ๊ตญ ๋ฉ”๋ฉ˜ํ†  ๊ฐ์ฒด๋Š” ํ•ด๋‹น ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๋‚ด๋ถ€ ๊ตฌํ˜„ ์‚ฌํ•ญ์€ ์ˆจ๊ฒจ์ง„๋‹ค.
    • ์‚ฌ์šฉ๋„ ๋„ฃ์–ด์คŒ์œผ๋กœ์จ ์ฒ˜๋ฆฌ๋˜๋‹ˆ ์บก์Šํ™” ๋ณดํ˜ธ๋œ๋‹ค.
  • ์ƒํƒœ ์ €์žฅ์— ๋Œ€ํ•œ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
    • Walker๋Š” ๋ฐ›์•„์„œ ๋„ฃ์–ด์ค„ ๋ฟ์ด๋‹ค.
  • ๋งŽ์€ ์–‘์˜ ์ •๋ณด ์ €์žฅ, ๋นˆ๋ฒˆํ•˜๊ฒŒ ์ƒํƒœ ๋Œ€์ฒดํ•  ๊ฒฝ์šฐ ๋น„์šฉ์ด ๋†’์•„์งˆ ์ˆ˜ ์žˆ๋‹ค.
    • ๊ณ„์†ํ•ด์„œ ์ €์žฅํ•˜๊ณ  ๋ฎ์–ด์จ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฐ์‚ฐ๋Ÿ‰์€ ์ฆ๋Œ€๋  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฉ”๋ฉ˜ํ†  ๊ฐ์ฒด๋ฅผ ๋ฐ›๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด (main)๋Š” ์ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋น„์šฉ์„ ์•Œ ์ˆ˜ ์—†๋‹ค.
    • ๋‹จ์ˆœํžˆ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉ๋งŒ ํ•œ๋‹ค๋ฉด, ๊ฐ์ฒด ๋‚ด๋ถ€ ๋ชจ๋“  ์ƒํƒœ๊ฐ’ ๋ณต์‚ฌ ๋“ฑ์˜ ๋น„์šฉ์„ ์•Œ์ง€๋ชปํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

์ƒ๊ฐํ•ด๋ณผ ์ 

  • Swift์—์„œ ๊ฐ์ฒด ์•„์นด์ด๋น™ ํ•˜๋Š” ๊ฒƒ์ด ์ด์™€ ๋น„์Šท (NSCoding)
  • NSObject์— ๋Œ€ํ•ด ์•„์นด์ด๋น™ํ•  ๋•Œ๋„ ํ•ด๋‹น ๊ฐ์ฒด ์•ˆ์—์„œ ์ •์˜ํ•ด์ฃผ์—ˆ์–ด์•ผ ํ•จ
  • ์™„๋ฒฝํžˆ ๋งค์นญ๋˜์ง€ ์•Š์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐ

Reference