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

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

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

  • ์ƒํƒœ๋ฅผ ๊ฐ์ฒดํ™” ํ•œ ํŒจํ„ด
  • ์กฐ๊ฑด์ ˆ์„ ํšจ๊ณผ์ ์œผ๋กœ ์ค„์—ฌ์ฃผ๋Š” ํŒจํ„ด

์˜ˆ์‹œ

  • ์–ด๋–ค ํ”„๋กœ๊ทธ๋žจ์—์„œ์˜ ๋™์ž‘์ด ๋…๋ฆฝ์ ์ด์ง€ ์•Š๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?
  • ์ฆ‰, ์ด์ „ ์ƒํƒœ์— ๋‹ค์Œ ๋™์ž‘์˜ ๊ฒฐ๊ณผ๊ฐ€ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ์ข…์† ์‚ฌ๊ฑด์ด๋ผ๋ฉด?
  • ์„œ๊ธฐ, ๊ฑท๊ธฐ, ๋›ฐ๊ธฐ, ์•‰๊ธฐ์˜ 4๊ฐ€์ง€ ๋™์ž‘์ด ์žˆ๋‹ค๊ณ  ํ•˜์ž.
  • ๋‹ค์Œ ๋™์ž‘์„ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š” ์ด์ „ ์ƒํƒœ๊ฐ€ ์–ด๋–ค ์ƒํƒœ๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๊ณ  ํ•ด๋ณด์ž.
  • ์ด๋Ÿด ๊ฒฝ์šฐ 4*4๋กœ 16๊ฐ€์ง€์˜ ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ๋‚˜์˜จ๋‹ค.
  • ๋งŒ์•ฝ ์กฐ๊ฑด๋ฌธ์„ ์“ด๋‹ค๋ฉด 16๊ฐœ๋ฅผ ๋ถ„๊ธฐ์ณ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ ์ƒํƒœ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๋‹ค.

  • ํ•ต์‹ฌ์€ ๋‚ด๊ฐ€ ์˜จ ์ƒํƒœ์—์„œ ๋‹ค์Œ์œผ๋กœ ์ƒํƒœ๋ฅผ ์ „์ด์‹œํ‚ค๋Š” ์ฑ…์ž„์„ State๊ฐ€ ๊ฐ–๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์ฆ‰, ์ƒํƒœ๋Š” ์ž์‹ ์œผ๋กœ๋ถ€ํ„ฐ ๋‹ค์Œ ์ƒํƒœ๋กœ ์ „ํ™˜๋˜์—ˆ์„ ๋•Œ์˜ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ด์•ผ ํ•œ๋‹ค.

Code

main

//
//  main.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal func main() {
 
    let player = Player(speed: 0)
    player.update(state: StandUpState(player: player))
 
    while true {
        print("ํ”Œ๋ ˆ์ด์–ด ์ƒํƒœ: \(player.state?.description ?? "")")
        print("์†๋„: \(player.speed) km/h")
        print("1: ์„œ๊ธฐ, 2: ์•‰๊ธฐ, 3: ๊ฑท๊ธฐ, 4: ๋›ฐ๊ธฐ, 5: ์ข…๋ฃŒ")
        print("")
 
        let input = readLine()
        guard let first = input?.components(separatedBy: " ").first,
              let command = Int(first) else {
            return
        }
 
        switch command {
        case 1:
            player.state?.standUp()
        case 2:
            player.state?.sitDown()
        case 3:
            player.state?.walk()
        case 4:
            player.state?.run()
        default:
            print("์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
            return
        }
    }
 
}
 
main()
 

Player

//
//  Player.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
public class Player {
 
    private(set) var speed: Int
    private(set) var state: State?
 
    internal init(speed: Int) {
        self.speed = speed
    }
 
    internal func update(state: State) {
        self.state = state
    }
 
    internal func update(speed: Int) {
        self.speed = speed
    }
 
    internal func talk(message: String) {
        print("ํ”Œ๋ ˆ์ด์–ด: \(message)")
    }
 
}
 

State

//
//  State.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal protocol State: Loggable {
 
    init(player: Player)
 
    func standUp()
    func sitDown()
    func walk()
    func run()
 
    var player: Player { get }
 
}
 
internal protocol Loggable {
 
    var description: String { get }
 
}
 

StandUpState

//
//  StandUpState.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal class StandUpState: State {
 
    required internal init(player: Player) {
        self.player = player
    }
 
    internal func standUp() {
        self.player.talk(message: "์–ธ์ œ ์›€์ง์ผ๊บผ์•ผ?")
    }
 
    internal func sitDown() {
        self.player.update(state: SitDownState(player: self.player))
        self.player.talk(message: "์•‰์œผ๋‹ˆ ํŽธํ•˜๊ณ  ์ข‹์•„์š”")
    }
 
    internal func walk() {
        self.player.update(speed: 5)
        self.player.update(state: WalkState(player: self.player))
        self.player.talk(message: "๊ฑท๊ธฐ๋Š” ์ œ2์˜ ์ƒ๊ฐํ•˜๊ธฐ๋‹ค..")
    }
 
    internal func run() {
        self.player.update(speed: 10)
        self.player.update(state: RunState(player: self.player))
        self.player.talk(message: "๊ฐ‘์ž๊ธฐ ๋›ด๋‹ค๊ณ ?")
    }
 
    internal let player: Player
 
}
 
extension StandUpState: Loggable {
 
    internal var description: String {
        "์ œ์ž๋ฆฌ์— ์„œ์žˆ์Œ"
    }
    
}
 

SitDownState

//
//  SitDownState.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal class SitDownState: State {
 
    required internal init(player: Player) {
        self.player = player
    }
 
    internal func standUp() {
        self.player.update(state: StandUpState(player: self.player))
        self.player.talk(message: "์ผ์–ด๋‚˜์ž..")
    }
 
    internal func sitDown() {
        self.player.talk(message: "์–ผ๋งˆ๋‚˜ ์˜ค๋ž˜ ์•‰์•„ ์žˆ์„ ์ƒ๊ฐ์ด์•ผ")
    }
 
    internal func walk() {
        self.player.update(state: StandUpState(player: self.player))
        self.player.talk(message: "์•‰์•„์„œ ์–ด๋–ป๊ฒŒ ๊ฑท๋‹ˆ ์ผ๋‹จ ์ผ์–ด๋‚˜์ž.")
    }
 
    internal func run() {
        self.player.update(state: StandUpState(player: self.player))
        self.player.talk(message: "์•‰์•„์„œ ์–ด๋–ป๊ฒŒ ๋›ฐ๋‹ˆ ์ผ๋‹จ ์ผ์–ด๋‚˜์ž.")
    }
 
    internal let player: Player
 
}
 
extension SitDownState: Loggable {
 
    internal var description: String {
        "์•‰์•„์žˆ์Œ"
    }
 
}
 

WalkState

//
//  WalkState.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal class WalkState: State {
 
    required internal init(player: Player) {
        self.player = player
    }
 
    internal func standUp() {
        self.player.update(speed: 0)
        self.player.update(state: StandUpState(player: self.player))
        self.player.talk(message: "๋ฉˆ์ถฐ")
    }
 
    internal func sitDown() {
        self.player.update(speed: 0)
        self.player.update(state: SitDownState(player: self.player))
        self.player.talk(message: "๊ฑท๋‹ค๊ฐ€ ์•‰๋‹ค๋‹ˆ ์—‰๋ฉ์ด ๊นŒ์ง„๋‹ค.")
    }
 
    internal func walk() {
        self.player.talk(message: "๊ทธ๋ž˜ ๊ณ„์† ๊ฑท์ž.")
    }
 
    internal func run() {
        self.player.update(speed: 20)
        self.player.update(state: RunState(player: self.player))
        self.player.talk(message: "๊ฑท๋‹ค๊ฐ€ ๋›ฐ๋ฉด ์†๋„๊ฐ€ ํ™• ์˜ค๋ฅด์ง€!")
    }
 
    internal let player: Player
 
}
 
extension WalkState: Loggable {
 
    internal var description: String {
        "๊ฑท๋Š” ์ค‘"
    }
 
}
 

RunState

//
//  RunState.swift
//  State
//
//  Created by Choiwansik on 2023/02/13.
//
 
import Foundation
 
internal class RunState: State {
 
    required internal init(player: Player) {
        self.player = player
    }
 
    internal func standUp() {
        self.player.update(speed: 0)
        self.player.update(state: StandUpState(player: self.player))
        self.player.talk(message: "๋›ฐ๋‹ค๊ฐ€ ์„ฐ๋”๋‹ˆ ๋ฌด๋ฆŽ์ด ์•„ํŒŒ")
    }
 
    internal func sitDown() {
        self.player.update(speed: 0)
        self.player.update(state: SitDownState(player: self.player))
        self.player.talk(message: "๋›ฐ๋‹ค๊ฐ€ ์•‰์œผ๋ผ๊ณ ? ์—‰๋ฉ์ด ๋‹ค๊นŒ์กŒ๋‹ค.")
    }
 
    internal func walk() {
        self.player.update(speed: 8)
        self.player.update(state: WalkState(player: self.player))
        self.player.talk(message: "์†๋„๋ฅผ ์ค„์ผ๊ฒŒ")
    }
 
    internal func run() {
        self.player.update(speed: self.player.speed + 2)
        self.player.talk(message: "๋” ๋นจ๋ฆฌ ๋›ฐ๋ผ๋Š” ์†Œ๋ฆฌ์ง€?")
    }
 
    internal let player: Player
 
}
 
extension RunState: Loggable {
 
    internal var description: String {
        "๋›ฐ๋Š” ์ค‘"
    }
 
}
 

ํ™œ์šฉ์„ฑ

  • ๊ฐ์ฒด์˜ ํ–‰๋™์ด ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋Ÿฐํƒ€์ž„์— ํ–‰๋™์ด ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•œ๋‹ค.
  • ํŠน์ • ์—ฐ์‚ฐ์— ๋ถ„๊ธฐ ์กฐ๊ฑด์ด ๋„ˆ๋ฌด ๋งŽ์„ ๊ฒฝ์šฐ

๊ฒฐ๊ณผ

  1. ์ƒํƒœ์— ๋”ฐ๋ฅธ ํ–‰๋™์„ ๋ชจ์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ๋ณ„๋„์˜ ๊ฐ์ฒด๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ์ƒํƒœ ์ „์ด๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.
    • ์ƒํƒœ์˜ ๋ณ€ํ™”๊ฐ€ ์›์ž์ ์œผ๋กœ ๋ฐ”๋€๋‹ค.
  3. ์ƒํƒœ ๊ฐ์ฒด๋Š” ๊ณต์œ ๋  ์ˆ˜ ์žˆ๋‹ค.
    • ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์ด๊ณณ ์ €๊ณณ์œผ๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

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

  • TCP ์—ฐ๊ฒฐ ํ”„๋กœํ† ์ฝœ์— ์ ์šฉํ–ˆ์—ˆ์Œ

Reference