GoF์˜ ๋””์ž์ธ ํŒจํ„ด, ์ฑ…์ž„์—ฐ์‡„ ํŒจํ„ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

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

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

  • ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ฑ…์ž„๋“ค์„ ๋™์ ์œผ๋กœ ์—ฐ๊ฒฐํ•ด์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ํŒจํ„ด
  • ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๊ฐ์ฒด์™€ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋“ค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ํŒจํ„ด
  • ๊ธฐ๋Šฅ์„ ํด๋ž˜์Šค๋ณ„๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•จ
  • ๊ฐ๊ฐ์˜ ํด๋ž˜์Šค์—์„œ ์ž์‹ ์˜ ์ฑ…์ž„๋งŒ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Œ

์˜ˆ์‹œ

  • ๋‘ ์˜ˆ์‹œ ๋ชจ๋‘ ์ˆœ์ฐจ์ ์œผ๋กœ ์ž์‹ ์ด ๋งก์€ ์ฑ…์ž„๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ๋„˜๊ธด๋‹ค.

GoF์ฑ…์—์„œ ๋‚˜์˜ค๋Š” ์ฑ…์ž„์—ฐ์‡„ ํŒจํ„ด Code

  • ์›๋ž˜์˜ ๋ชจ์–‘๋Œ€๋กœ ์ ์–ด๋ณด๊ธด ํ–ˆ์œผ๋‚˜, setNext์ž์ฒด๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์—†๋‹ค.
  • ๋ฐ‘์—์„œ ์„ค๋ช…ํ•˜๊ฒ ์œผ๋‚˜, ๊ฐœ์ธ์ ์œผ๋กœ ์ด ์˜ˆ์‹œ๋Š” ์ข‹์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

Handler

//
//  Handler.swift
//  ChainOfResponsibility
//
//  Created by Choiwansik on 2023/01/16.
//
 
import Foundation
 
internal protocol Handler {
 
    var nextHandler: Handler? { get set }
 
    mutating func setNext(handler: Handler) -> Handler
 
    func run(url: URL)
 
    func process(url: URL)
 
}
 
extension Handler {
 
    internal mutating func setNext(handler: Handler) -> Handler {
        self.nextHandler = handler
        return handler
    }
 
    internal func run(url: URL) {
        self.process(url: url)
 
        if let nextHandler {
            nextHandler.run(url: url)
        }
    }
 
}
 

ProtocolHandler

//
//  ProtocolHandler.swift
//  ChainOfResponsibility
//
//  Created by Choiwansik on 2023/01/16.
//
 
import Foundation
 
internal class ProtocolHandler: Handler {
 
    internal func process(url: URL) {
        if let scheme = url.scheme {
            print("Protocol: \(scheme)")
        } else {
            print("No Protocol")
        }
    }
 
    internal var nextHandler: Handler?
 
}
 

DomainHandler

//
//  DomainHandler.swift
//  ChainOfResponsibility
//
//  Created by Choiwansik on 2023/01/16.
//
 
import Foundation
 
internal class DomainHandler: Handler {
 
    internal func process(url: URL) {
        if let host = url.host {
            print("Domain: \(host)")
        } else {
            print("No Domain")
        }
    }
 
    internal var nextHandler: Handler?
 
}
 

PortHandler

//
//  PortHandler.swift
//  ChainOfResponsibility
//
//  Created by Choiwansik on 2023/01/16.
//
 
import Foundation
 
internal class PortHandler: Handler {
 
    internal func process(url: URL) {
        if let port = url.port {
            print("Port: \(port)")
        } else {
            print("No Port")
        }
    }
 
    internal var nextHandler: Handler?
 
}
 

main

//
//  main.swift
//  ChainOfResponsibility
//
//  Created by Choiwansik on 2023/01/16.
//
 
import Foundation
 
internal func ๊ธฐ์กด์˜์œ„ํ‚คํ”ผ๋””์•„์—์„œ๋‚˜์˜ค๋Š”์ฑ…์ž„์—ฐ์‡„ํŒจํ„ด() {
    var protocolHandler: Handler = ProtocolHandler()
    var domainHandler: Handler = DomainHandler()
    var portHandler: Handler = PortHandler()
 
    protocolHandler
        .setNext(handler: domainHandler)
        .setNext(handler: portHandler)
 
    protocolHandler.run(url: URL(string: "https://naver.com"))
 
    // Swift์—์„œ๋Š” return ๊ฐ’์ด immutable์ด๋ผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค!!
    // ์• ์ดˆ์— ์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๋ณธ๋‹ค.
}
 
๊ธฐ์กด์˜์œ„ํ‚คํ”ผ๋””์•„์—์„œ๋‚˜์˜ค๋Š”์ฑ…์ž„์—ฐ์‡„ํŒจํ„ด()

์˜ฌ๋ฐ”๋ฅธ ์ฑ…์ž„ ์—ฐ์‡„ ํŒจํ„ด

  • ๊ตณ์ด setNext()๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๊ฐ€?
    • ๊ด€๋ฆฌ ๊ฐ์ฒด๋ฅผ ํ•˜๋‚˜ ๋‘๊ณ , ๊ฑฐ๊ธฐ์„œ ๋‹ค์Œ์œผ๋กœ๋งŒ ๋„˜๊ฒจ์ฃผ๋ฉด ๋˜์ง€ ์•Š๋Š”๊ฐ€?
    • ์—ฐ์‡„๋ฅผ ๊ผญ ํด๋ž˜์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•ด์•ผ ํ•˜๋Š”๊ฐ€? ์ฑ…์ž„์„ ๋‚˜๋ˆ„๋Š”๊ฒŒ ๊ด€๋ฆฌ์ธก๋ฉด์—์„œ ์ข‹์ง€ ์•Š์€๊ฐ€?
  • ์ž๊ธฐ ์ž์‹ ์„ ๋ฆฌํ„ดํ•˜๋Š” ํ”Œ๋ฃจ์–ธํŠธ ์ธํ„ฐํŽ˜์ด์Šค ๋ฐฉ์‹๋„ ์•„๋‹ˆ๋‹ค.
  • ์˜คํžˆ๋ ค ํ˜ผ๋ž€์„ ๊ฐ€์ค‘์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•.
  • ์—ฐ์‡„์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์ฑ…์ž„์„ ์ˆ˜ํ–‰, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ฑ…์ž„์„ ๊ฒฉ๋ฆฌํ•˜์—ฌ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ๋ณธ์งˆ์ ์œผ๋กœ ์›ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด,
  • ๊ตณ์ด ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๊ฐ™์€ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Chain Of Responsibility๊ธ€์„ ํ†ตํ•ด ๋ณ€๊ฒฝ๋œ ๋ฐฉ์‹์„ ํ™•์ธํ•˜์ž.

ํ™œ์šฉ์„ฑ

  • ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด ์ง‘ํ•ฉ์ด ๋™์ ์œผ๋กœ ์ •์˜๋˜์–ด์•ผ ํ• ๋•Œ

๊ฒฐ๊ณผ

  • ๊ฐ์ฒด๊ฐ„ ํ–‰๋™์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง„๋‹ค.
    • ๋‹ค๋ฅธ ๊ฐ์ฒด๊ฐ€ ์–ด๋–ป๊ฒŒ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๋ชฐ๋ผ๋„ ๋œ๋‹ค.
    • ๊ทธ๋ƒฅ ๋„˜๊ธฐ๊ณ , ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ๋งŒ ํ™•์‹ ํ•˜๋ฉด ๋œ๋‹ค.
  • ์ฑ…์ž„์„ ๋‚˜๋ˆ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
    • ๋‹จ๊ณ„๋ณ„๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๊ทธ ๋‹จ๊ณ„๋ณ„๋กœ ํด๋ž˜์Šค๋ฅผ ๋‚˜๋ˆ„์–ด ์ฑ…์ž„์„ ๋ถ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์ด ๋ณด์žฅ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.

๊ด€๋ จ ํŒจํ„ด๊ณผ ์ฐจ์ด์ 

  • 24. Strategy: ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ถ„๋ฆฌ
  • 17. Command: ์–ด๋–ค ๋™์ž‘์„ ๋ถ„๋ฆฌ
  • 16. Chain of Responsibility: ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ๊ณผ ์†ก์‹ ์„ ๋ถ„๋ฆฌ

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

  • next๋กœ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์ด ์ข‹์•„๋ณด์ด์ง€๋Š” ์•Š๋Š”๋‹ค.
  • ๊ตณ์ด ์ €๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๋  ๋“ฏํ•˜๋‹ค.
  • ํŒจํ„ด์— ๋งค๋ชฐ๋˜์ง€ ๋ง์ž.

Reference