TIL/CS(feat. Swift)
디자인 패턴 훑어보기_옵저버 패턴
여의도사노비
2023. 2. 6. 19:46
728x90
옵저버 패턴
옵저버 패턴(Observer Pattern)은 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려 주는 디자인 패턴이다. 여기서 주체란 객체의 상태 변화를 보고 있는 관찰자이며, 옵저버들이란 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 '추가 변화 사항'이 생기는 객체들을 의미한다.
옵저버 패턴을 활용한 서비스로는 트위터가 있다. 또한 옵저버 패턴은 주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.
예를들어 주체라고 볼 수 있는 모델에서 변경 사항이 생겨 update() 메서드로 옵저버인 뷰에 알려주고 이를 기반으로 컨트롤러 등이 작동하는 것이다.
장점
- Open / Close 원칙을 지킬 수 있다. Subject(Publisher)의 코드를 수정하지 않고 새로운 Observer(Subscriber) 클래스를 추가할 수 있다.
- 런타임에서 객체간 관계를 설정할 수 있다.
단점
- Observer(Subscriber)에게 알림이 가는 순서는 보장하지 않는다.
- Observer, Subject의 관계가 잘 정의되지 않으면 원하지 않는 동작이 발생할 수도 있다.
Swift로 보는 간단한 예시
// Subject(Publisher) Interface
protocol Publisher {
var observers: [Observer] { get set }
func subscribe(observer: Observer)
func unSubscribe(observer: Observer)
func notify(message: String)
}
// Observer(Subscriber) Interface
protocol Observer {
var id: String { get set }
func update(message: String)
}
// Concrete Subject(Publisher)
class AppleStore: Publisher {
var observers: [Observer]
init(observers: [Observer]) {
self.observers = observers
}
func subscribe(observer: Observer) {
self.observers.append(observer)
}
func unSubscribe(observer: Observer) {
if let index = self.observers.firstIndex(where: { $0.id == observer.id }) {
self.observers.remove(at: index)
}
}
func notify(message: String) {
for observer in observers {
observer.update(message: message)
}
}
}
// Concrete Observer(Subscriber)
class Customer: Observer {
var id: String
init(id: String) {
self.id = id
}
func update(message: String) {
print("\(id)님 \(message)수신\n")
}
}
(코드 참고: https://icksw.tistory.com/257)
옵저버 패턴은 주로 UI의 변경, 알림, 구독과 같은 이유로 사용되는데
주로 데이터의 흐름과 관련있는 Combine이나 특정 변화를 인식하게 해주는 Notification에 자주 사용된다.