오늘은 디자인 패턴 중 옵저버 패턴에 대해서 공부할 예정입니다. 옵저버 패턴은 행동 패턴에 속해있는 디자인 패턴 중 하나입니다.
행동 패턴이란?
행동 패턴은 객체나 클래스 간의 상호작용을 정의하여 책임 분배를 용이하게 하고, 상호작용을 캡슐화하는 디자인 패턴입니다. 이러한 패턴은 객체들이 협력하여 작업을 수행하는 방법을 정의하고, 상호작용의 유연성을 높여줍니다.
옵저버 패턴(Observer Pattern)이란?
옵저버 패턴은 객체의 상태 변화를 관찰하는 옵저버가 상태 변화를 감지하고, 상태에 변화가 있을 때마다 업데이트를 받는 패턴입니다. 하나의 Subject 객체의 상태가 변경되면 이를 의존하고 있는 여러 옵저버 객체들에게 알림이 가고 업데이트를 수행하게 됩니다. 이를 통해 일대다의 의존성을 갖게 됩니다.
옵저버 패턴의 구성 요소
Observer 란?
- 주제로부터 통지를 받으면 특정 동작을 수행하는 객체
- 주제의 상태에 따라 자신의 상태나 행동을 업데이트
Subject 란?
- 옵저버를 관리하는 메커니즘을 제공하는 객체
- Subject는 옵저버 등록, 옵저버 알림, 옵저버 해제의 세 가지 핵심 역할을 수행
옵저버 패턴의 구현 예제
swift코드 복사protocol Subject {
func addObserver(observer: Observer)
func removeObserver(observer: Observer)
func notify(message: String)
}
protocol Observer: AnyObject {
func update(message: String)
}
class Owner: Subject {
private var observers: [Observer] = []
func addObserver(observer: Observer) {
self.observers.append(observer)
}
func removeObserver(observer: Observer) {
observers = observers.filter { $0 !== observer }
}
func notify(message: String) {
for observer in observers {
observer.update(message: message)
}
}
}
class Pet: Observer {
let name: String
init(name: String) {
self.name = name
}
func update(message: String) {
print("\(name) \(message)")
}
}
let owner = Owner()
let cat = Pet(name: "고양이")
let dog = Pet(name: "강아지")
owner.addObserver(observer: cat)/*
고양아 점심 먹자~
멍멍아 점심 먹자~
멍멍아 저녁 먹자~
*/
위 코드는 옵저버 패턴을 Swift로 구현한 예제입니다. Subject는 옵저버를 추가, 제거하고 알림을 보냅니다.
Combine에서의 옵저버 패턴 적용
옵저버 패턴은 iOS 개발에서 자주 접하는 Combine 프레임워크에서도 사용됩니다. Combine은 데이터 스트림과 변화하는 데이터에 반응형 프로그래밍을 쉽게 할 수 있도록 해주는 프레임워크입니다.
Combine의 구성 요소
Publisher
- 데이터를 제공하고, 구독자가 데이터 스트림을 받을 수 있도록 합니다. 데이터가 변경되거나 이벤트가 발생할 때, Publisher는 구독자에게 새로운 데이터를 전달합니다.
Subscriber
- Publisher가 제공하는 데이터를 수신합니다. 데이터 스트림의 변경 사항에 반응하여 처리합니다.
Combine을 활용한 옵저버 패턴 예제
swift코드 복사import Combine
class Owner {
// 메시지를 발행하는 PassthroughSubject
var messagePublisher = PassthroughSubject<String, Never>()
func notify(message: String) {
messagePublisher.send(message)
}
}
class Pet {
let name: String
var cancellable: AnyCancellable?
init(name: String, owner: Owner) {
self.name = name
// 구독 설정
self.cancellable = owner.messagePublisher.sink { [weak self] message in
self?.update(message: message)
}
}
func update(message: String) {
print("\(name) \(message)")
}
}
let owner = Owner()
let cat = Pet(name: "고양이", owner: owner)
let dog = Pet(name: "강아지", owner: owner)
owner.notify(message: "점심 먹자~")
cat.cancellable?.cancel()
owner.notify(message: "저녁 먹자~")
/*
고양이 점심 먹자~
강아지 점심 먹자~
강아지 저녁 먹자~
*/
위 코드는 Combine을 사용하여 옵저버 패턴을 구현한 예제입니다. PassthroughSubject는 메시지를 발행하는 Publisher, sink 메서드는 메시지를 수신하는 Subscriber 역할을 합니다.
옵저버 패턴은 간단하면서도 여러 코드에 적용될 수 있어 활용도가 높은 패턴입니다. iOS 개발을 공부할 때 Combine과 함께 옵저버 패턴을 이해하면 더욱 효과적으로 학습할 수 있습니다.