Design Patterns

Observer Pattern

JoonSwift 2021. 6. 3. 15:08

Observer Pattern에 대해서 공부를 해보았습니다. Observe Pattern은 하나의 Object가 다른 Object의 변화를 관찰하는 패턴입니다. 

 

Subscriber

Subscriber는 Observer의 역할을 하는 친구입니다. 관찰하고 싶은 Object를 관찰하고, 변경이 일어나면 Update를 받습니다.

 

Publisher

Publisher는 관찰이 가능한 Object입니다. 다른 Object가 자신을 관찰할 수 있게 해주고, 변경사항을 보내는 역할을 합니다. 

 

Value

Value는 값의 변경이 일어나는 근본적인 Object입니다.

 

이들의 관계를 그림으로 표현해보면 아래와 같은 모습입니다.

Swift 5.1 부터 이 Observer Pattern을 더 편하게 활용할 수 있는 Combine이라는 프레임워크가 추가되었습니다. 이 Combine 내의 Publisher를 활용해서 Observer Pattern의 간단한 코드를 작성해보겠습니다. 

import Combine

class BitCoin {
    @Published var price: Int
    
    init(price: Int) {
        self.price = price
    }
}

BitCoin이라는 Class를 만들고 내부에 price라는 Int형 변수를 @Published 키워드를 붙여 만들어 주었습니다. 이제 ViewController를 만들어보겠습니다.

class BitCoinViewController: UIViewController {
    @IBOutlet var bitcoinPriceLabel: UILabel?
    
    var todayBitCoin: BitCoin!
    var publisher: Published<Int>.Publisher!
    var subscriber: AnyCancellable?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        todayBitCoin = BitCoin(price: 4300)
        publisher = todayBitCoin.$price
        subscriber = publisher.sink(receiveValue: { [weak self] price in
            guard let self = self else { return }
            print("Today's Bitcoin Price is $\(price)")
            self.bitcoinPriceLabel?.text = "$\(price)"
        })
        nextDayPrice(5000)
        
    }
    
    func nextDayPrice(_ price: Int) {
        todayBitCoin.price = price
    }
}

BitCoinViewController에서 todayBitCoin, publisher, subscriber가 있습니다.

해당 프로퍼티들을 viewDidLoad()에서 초기화 시켜주는 코드를 작성해보았습니다.

우선 publisher의 타입이 신기하게 생긴 Published<Int>.Publisher 입니다. 이 Object를 todayBitCoin.$price로 초기화 시켜주면서 todayBitCoin의 price 값의 변경을 감지하게 됩니다. 

다음은 subscriber입니다. subscriber는 publisher의 sink메서드를 호출하고 있습니다. 이는 처음 Value가 이니셜라이저 될 때와, 해당 값이 변경될 때 마다 클로저 내부의 코드를 실행하게 됩니다. 

그럼 위의 코드를 실행시키면 나오는 결과는! 

이러한 결과가 나오게 됩니다. 아래의 nextDayPrice(5000)의 실행과 함께 price의 값이 변경되니 subscriber의 클로저가 실행된 모습을 볼 수 있습니다. 

 

그리고 subscriber의 해제는 간단하게 subscriber = nil 코드를 통해서 더이상 publisher에게서 오는 값의 변경을 받지 않게 됩니다.

 

위의 코드로 알 수 있는 점은 지금은 ViewController가 Subscriber를 들고 있고, Model이 Publisher를 들고 있다는 것을 알 수 있습니다. 그래서 Model은 ViewController에 대해 아무것도 몰라도 자신의 값의 변경을 ViewController에게 알려줄 수 있습니다.