💌 Design Pattern

[Design Pattern] Observer Pattern (옵저버패턴) with Swift

exception_log 2022. 2. 22. 22:44

안녕하세요! 조이임다!

저희 회사는 코로나로 인해서 원래도 상시 재택을 했지만  더 많이 재택근무를 하게 되었어요ㅠ_ㅠ

3차 접종까지 마쳤음에도 혹시나 걸릴까봐 저도 이번주는 오늘 빼고는 다 재택이랍니당 (TMI 방출)

이 글을 보시는 모든 분들 항상 건강하시길 바랍니다!!

 

 

Observer Pattern 개요

옵저버는 관찰하는 개체에 발생하는 모든 이벤트에 대해 여러 개체에 알리는 구독 메커니즘을 정의할 수 있는 동작 디자인 패턴
관찰자 패턴은 구독자 인터페이스를 구현하는 모든 개체에 대해 이러한 이벤트를 구독하거나 구독을 취소할 수 있는 방법을 제공한다.

 

실제 상황에서 생각해보기

  • 서로의 정보를 주고받는 과정에서 정보의 단위가 클수록, 객체들의 규모가 클수록 복잡성이 증가하게 된다. 이때 가이드라인을 제시해줄 수 있는 것이 '옵저버 패턴' 이다.
  • 구독자, 고객들은 정보를 얻거나 받아야 하는 주체와 관계를 형성하게 된다. 관계가 지속되다가 정보를 원하지 않으면 해제할 수도 있다.
  • 이때, 객체와의 관계를 맺고 끊는 상태 변경 정보를 Observer에 알려줘서 관리하는 것을 말한다.
  • Swift에서 옵저버 패턴은 GUI 구성 요소에서 매우 일반적으로 사용된다. 옵저버 패턴은 클래스와 결합하지 않고 다른 개체에서 발생하는 이벤트에 반응하는 방법을 제공한다고 한다.

 

코드로 확인해보기

import XCTest

class Subject {
    
    var state: Int = { return Int(arc4random_uniform(10)) }()

    private lazy var observers = [Observer]()

    func attach(_ observer: Observer) {
        print("Subject: Attached an observer.\n")
        observers.append(observer)
    }

    func detach(_ observer: Observer) {
        if let idx = observers.firstIndex(where: { $0 === observer }) {
            observers.remove(at: idx)
            print("Subject: Detached an observer.\n")
        }
    }

    func notify() {
        print("Subject: Notifying observers...\n")
        observers.forEach({ $0.update(subject: self)})
    }

    func someBusinessLogic() {
        print("\nSubject: I'm doing something important.\n")
        state = Int(arc4random_uniform(10))
        print("Subject: My state has just changed to: \(state)\n")
        notify()
    }
}

protocol Observer: AnyObject {

    func update(subject: Subject)
}


class ConcreteObserverA: Observer {

    func update(subject: Subject) {

        if subject.state < 3 {
            print("ConcreteObserverA: Reacted to the event.\n")
        }
    }
}

class ConcreteObserverB: Observer {

    func update(subject: Subject) {

        if subject.state >= 3 {
            print("ConcreteObserverB: Reacted to the event.\n")
        }
    }
}

class ObserverConceptual: XCTestCase {

    func testObserverConceptual() {

        let subject = Subject()

        let observer1 = ConcreteObserverA()
        let observer2 = ConcreteObserverB()

        subject.attach(observer1)
        subject.attach(observer2)

        subject.someBusinessLogic()
        subject.someBusinessLogic()
        subject.detach(observer2)
        subject.someBusinessLogic()
    }
}

오늘도 제가 참고하는 사이트의 컨셉 샘플 코드를 가져와봤어요

Observer 패턴은.. 제가 요새 RxSwift를 공부하고 있는데, 이 때도 Observable이라는 등장하기 때문에 개념을 한번 알아두면 활용도가 꽤나 높을것이고 그 때 이해하기도 쉽다고 생각합니다! (개인적인..생각..)

저는 회사에서는 RxSwift를 사용하고 있지는 않아서 아직 많이 부족하지만.. 추후에 Rx도 포스팅하도록 할거에요!!!! (다짐)

 

 

감사합니다 :) 

 

오류, 문제 지적은 댓글로 달아주세요!

 

 

참고 : https://refactoring.guru/design-patterns/observer

반응형