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

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

Observer 패턴

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

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

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

구현

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

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

예제

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

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

1
2
3
4
5
6
7
8
protocol Observable {
func addObserver(_ observer: Observer)
func removeObserver(_ observer: Observer)
}
protocol Observer: class {
func update(_ temp: Float, density: Float)
}

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

1
2
3
4
5
6
7
8
9
10
11
class Observation: Observable {
var observers = [Observer]()
func addObserver(_ observer: Observer) {
observers.append(observer)
}
func removeObserver(_ observer: Observer) {
observers = observers.filter({ $0 !== observer })
}
}

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

1
2
3
4
5
6
7
8
9
10
class DustMeter: Observation {
var temperature: Float = 0.0
var density: Float = 0.0
func notify() {
for observer in observers {
observer.update(temperature, density: density)
}
}
}

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

1
2
3
4
5
6
7
8
9
10
11
12
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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