예시 코드
class Subject {
private val observers = mutableListOf<Observer>()
fun registerObserver(observer: Observer) {
observers.add(observer)
}
fun unregisterObserver(observer: Observer) {
observers.remove(observer)
}
fun notifyObservers() {
for (observer in observers) {
observer.notifyObserver()
}
}
}
interface Observer {
fun notifyObserver()
}
class ConcreteObserverA : Observer {
override fun notifyObserver() {
// Do something
}
}
class ConcreteObserverB : Observer {
override fun notifyObserver() {
// Do something
}
}
개념
Observer Pattern은 한 객체의 상태변화를 다른 객체 그룹에 알려야 할 때 사용되는 디자인 패턴이다. 상태변화를 알려야하는 객체 그룹을 미리 알 수 없거나, 그룹요소들이 동적으로 변경되는 경우 사용할 수 있다.
비유
단체 채팅방
상황
- 기능 → 단체 채팅방
- 행동 → 한 명이 채팅을 보내면 채팅방의 구성원들이 알람 수신
적용
interface EventListener { fun update(msg: String) } class ChattingMessageListener(val name: String) : EventListener { override fun update(msg: String) { createPushNotification(msg) } }
class ChattingRoom { private val members = mutableListOf<ChattingMessageListener>() fun addMember(member: ChattingMessageListener) { members.add(member) } fun removeMember(with = member: ChattingMessageListener) { members.remove(member) } fun sendMessageToAllMembers(msg: String, author: String) { for (member in members) { member.update(msg, author) } } }
fun main() { val chattingRoom = ChattingRoom() val members = arrayOf<ChattingMessageListener>( ChattingMessageListener("John"), ChattingMessageListener("Choi"), ChattingMessageListener("Yoon") ) members.forEach { member -> chattingRoom.addMember(with = member) } chattingRoom.sendMessage("Hello", members[1].name) }
주식 알림
상황
- 기능 → 주식 가격 알림
- 행동 → 종목 가격이 변경되면 투자자들에게 알림을 보내줌
적용
abstract class Stock(val symbol: String, private val price: Double) { private val investors = mutableListOf<IInvestor>() fun attach(investor: IInvestor) { investors.add(investor) } fun detach(investor: IInvestor) { investors.remove(investor) } fun notify() { for (investor in inverstors) { investor.update(this) } } fun setPrice(price: Double) { this.price = price notify() } }
class Apple(symbol: String, price: Double) : Stock(symbol, price)
interface IInvestor { fun update(stock: Stock) }
class Investor(val name: String) : IInvestor { override fun update(stock: Stock) { println("$name is notified that ${stock.symbol}'s price change to ${stock.price}") } }
장단점
장점
- OCP (개방-폐쇄 원칙)
- 확장에는 열려있고, 수정에는 닫혀 있어야 한다.
단점
- 레이스 컨디션
- 알림을 보내는 중에 옵저버가 등록됐을 때
- 알림을 보내는 중에 옵저버가 등록해제됐을 때
- 순환 실행
- 이벤트 X가 발생했을 때, 옵저버 A가 옵저버 B를 갱신하고, 옵저버 B가 옵저버 A를 갱신한다면 순환 실행이 일어난다.
출처
https://refactoring.guru/ko/design-patterns/observer
https://ko.wikipedia.org/wiki/옵서버_패턴
Uploaded by N2T
'Programming > 디자인패턴' 카테고리의 다른 글
[Kotlin] Command Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.17 |
---|---|
[Kotlin] Singleton Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.17 |
[Kotlin] Factory Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.06 |
[Kotlin] Decorator Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.06 |
[Kotlin] Strategy Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.05 |