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

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

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

  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์™€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•ด์ฃผ๋Š” ํŒจํ„ด
  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ๊ธฐ์กด์˜ ์†Œ์Šค ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ์ƒˆ๋กœ์šด ํด๋ž˜์Šค ์ถ”๊ฐ€๋งŒ์œผ๋กœ ํ™•์žฅ ๊ฐ€๋Šฅํ•จ
  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋Š” Composite Pattern์„ ์‚ฌ์šฉํ•จ

์˜ˆ์‹œ

Code

main

//
//  main.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal func main() {
    let list1 = ItemList()
    list1.add(unit: Item(value: 10))
    list1.add(unit: Item(value: 20))
    list1.add(unit: Item(value: 30))
 
    let list2 = ItemList()
    list2.add(unit: Item(value: 40))
    list2.add(unit: Item(value: 50))
    list2.add(unit: list1)
 
    let list3 = ItemList()
    list3.add(unit: Item(value: 60))
    list3.add(unit: list1)
    list3.add(unit: list2)
 
    let sum = SumVisitor()
    let avg = AvgVisitor()
 
    list1.accept(visitor: sum)
    list1.accept(visitor: avg)
    print("List1 SUM: \(sum.value)")
    print("List1 AVG: \(avg.value)")
 
    list2.accept(visitor: sum)
    list2.accept(visitor: avg)
    print("List2 SUM: \(sum.value)")
    print("List2 AVG: \(avg.value)")
 
    list3.accept(visitor: sum)
    list3.accept(visitor: avg)
    print("List3 SUM: \(sum.value)")
    print("List3 AVG: \(avg.value)")
 
}
 
main()
 
 
List1 SUM: 60
List1 AVG: 20.0
List2 SUM: 210
List2 AVG: 26.25
List3 SUM: 480
List3 AVG: 28.235294117647058

Unit

//
//  Unit.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal protocol Unit {
 
    func accept(visitor: Visitor)
    
}
 

Item

//
//  Item.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal struct Item: Unit {
 
    internal let value: Int
 
    internal func accept(visitor: Visitor) {
        visitor.visit(unit: self)
    }
    
}
 

ItemList

//
//  ItemList.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal class ItemList: Unit {
 
    internal func add(unit: Unit) {
        self.list.append(unit)
    }
 
    internal func accept(visitor: Visitor) {
        self.list.forEach { visitor.visit(unit: $0) }
    }
 
    private(set) var list = Array<Unit>()
 
}
 

Visitor

//
//  Visitor.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal protocol Visitor {
 
    func visit(unit: Unit)
    
}
 

SumVisitor

//
//  SumVisitor.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal class SumVisitor: Visitor {
 
    internal var value: Int {
        self.sum
    }
 
    internal func visit(unit: Unit) {
        if let item = unit as? Item {
            sum += item.value
        } else {
            unit.accept(visitor: self)
        }
    }
 
    private(set) var sum: Int = .zero
 
}
 

AvgVisitor

//
//  AvgVisitor.swift
//  Visitor
//
//  Created by Choiwansik on 2023/02/21.
//
 
import Foundation
 
internal class AvgVisitor: Visitor {
 
    internal var value: Double {
        Double(self.sum) / Double(self.count)
    }
 
    internal func visit(unit: Unit) {
        if let item = unit as? Item {
            self.sum += item.value
            self.count += 1
        } else {
            unit.accept(visitor: self)
        }
    }
 
    private(set) var sum = 0
    private(set) var count = 0
}
 

ํ™œ์šฉ์„ฑ

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

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

  • ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€๋  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๋™์ž‘์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ๊ฐ์ฒด ์š”์†Œ๊ฐ€ Visitor ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค.

Reference