본문 바로가기

Programming/iOS

Observer Pattern in Swift

반응형

Observer패턴이란 무엇인지에 대해서 알아보도록 하겠습니다.
(제가 이해하고 있는 기준이라 혹 잘못된 내용이 있으면 알려주시기 바랍니다.)

옵저버 패턴 설명은 wikipedia를 토대로 작성하였습니다.

Observer 패턴

옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다.

쉽게 예를 들어 설명하도록 해보겠습니다.

요즘 미세먼지가 심하잖아요? 저도 미세먼지에 민감한 사람중 한명인데요. 그래서 얼만큼 미세먼지 농도가 나오는지 미세먼지를 측정하고 기록하는 모델을 하나 만들었습니다.
이 소식을 듣고 저처럼 미세먼지에 민감한 분들이 매 시간마다 와서 미세먼지 농도가 얼마나 되는지 물어봅니다. 처음에는 일일이 알려주다보니 제 시간을 너무 많이 뺏기는거 같고, 제 업무를 할 수가 없을 지경에 이르렀습니다.
그리하여 “원하는 데이터 및 특정 상태가 되면 자동으로 알려주겠다”라고 하고 알림 시스템을 만들어 버립니다. 이 소식을 듣고 여러분은 알림을 받기 위해 제 모델에 등록을 합니다.
다음 날, 아침에 일어나 보니 미세먼지 농도가 나쁨으로 변경이 됐습니다. 시스템을 이를 감지하고 알림을 등록해준 분들에게 이 상태를 전송하게 됩니다.

구현

옵저버 패턴의 핵심은 옵저버 또는 리스너(listener)라 불리는 하나 이상의 객체(사용자)가 관찰 대상(미세먼지 측정 시스템)이 되는 객체에 등록시킵니다. 이 관찰 대상의 상태가 변경되면 옵저버들은 이 객체가 발생시키는 이벤트를 받아 각각 행동을 하게 됩니다.

위 예를 토대로 UML 다이어그램으로 표현해보면 아래와 같습니다.

예제

위 다이어그램을 토대로 아래 예제를 구성했습니다.

각 옵저버를 등록 및 해제할 수 있는 protocol 생성

protocol Observable {
    func addObserver(_ observer: Observer)
    func removeObserver(_ observer: Observer)
}
protocol Observer: class {
    func update(_ temp: Float, density: Float)
}

 

옵저버의 등록 및 해제를 실제로 담당하는 클래스 생성

class Observation: Observable {
    var observers = [Observer]()
    func addObserver(_ observer: Observer) {
        observers.append(observer)
    }
    func removeObserver(_ observer: Observer) {
        observers = observers.filter({ $0 !== observer })
    }
}

 

미세먼지 농도를 측정하여 알림을 보내는 클래스

class DustMeter: Observation {
    var temperature: Float = 0.0
    var density: Float = 0.0
    func notify() {
        for observer in observers {
            observer.update(temperature, density: density)
        }
    }
}

 

미세먼지 농도 상태를 알림 받을 수 있는 유저

class Subscriber: Observer {
    var name: String = ""
    func update(_ temp: Float, density: Float) {
        print("name: \(name), temp: \(temp) density: \(density)")
    }
    init(name: String) {
        self.name = name
    }
}

 

위의 구성을 토대로 구현한 Controller

class ViewController: UIViewController {
    let dustMeter = DustMeter()
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 관찰자
        let user1 = Subscriber(name: "Tom")
        let user2 = Subscriber(name: "Sam")
        let _ = Subscriber(name: "Kim")
        
        // 알림을 받을 유저 추가
        dustMeter.addObserver(user1)
        dustMeter.addObserver(user2)
        
        // 알림을 더이상 받지 않을 유저
        dustMeter.removeObserver(user1)
    }
}

extension ViewController {
    @IBAction func clickedButton() {
        dustMeter.temperature = 32
        dustMeter.density = 80
        dustMeter.notify()
    }
}

 

결과 값

Source

위 예제에 대한 소스는 github에서 다운 받으실 수 있습니다.

 

참고

http://kyejusung.com
http://copynull.tistory.com/140

반응형