티스토리 뷰
정의
- 상태를 관리하는 Subject 객체가 자신을 구독한 Observer 객체들의 참조를 보관하고 있다가, 상태가 변경되면 등록된 Observer들의 공통 알림 메서드를 호출하여 변경 사실이나 변경된 데이터를 전달하는 행동 패턴
목적
- Observer 패턴을 씀으로서 알림을 주는 객체는 마치 구독자 관리 시스템처럼 알림을 받는 대상의 참조값과 알림 기능의 호출 method만 가지만 된다.
- 알림을 받는 객체는 알림을 주는 객체에게 알림을 받겠다고 요청만 하면, 알림을 주는 객체는 알림을 받겠다는 객체의 참조값만을 저장하고 관리하여 해당 객체들에게만 알림을 주는 함수를 호출하면 알림을 받는 객체들에게만 알림을 줄 수 있다.
코드
전체 코드
package designpattern
interface Observer {
fun update(message: String) : String
}
class Customer(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "일반 고객 $name: $message"
}
}
class VipCustomer(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "VIP 고객 $name: 우선 알림 - $message"
}
}
class Admin(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "관리자 $name: 입고 내역 기록 - $message"
}
}
class Store {
private val observers = mutableListOf<Observer>()
fun subscribe(observer: Observer) {
observers.add(observer)
}
fun notifyObservers(message: String): List<String> {
val results = mutableListOf<String>()
for (observer in observers) {
val result = observer.update(message)
results.add(result)
}
return results
}
}
알림을 주는 클래스
class Store {
private val observers = mutableListOf<Observer>()
fun subscribe(observer: Observer) {
observers.add(observer)
}
fun notifyObservers(message: String): List<String> {
val results = mutableListOf<String>()
for (observer in observers) {
val result = observer.update(message)
results.add(result)
}
return results
}
}
- 알림을 주는 주체 클래스인 Store 클래스 인스턴스는 구독자가 누구인지만 관리하면 되므로 편하다
- private val observers = mutableListOf<Observer>() 는 각 사용자 객체에 해당하는 참조값을 저장하는 리스트 객체를 선언하고, 해당 객체안에 사용자 참조값을 넣어 저장한다.
- 즉 알림을 주는 주체인 Store 클래스 인스턴스는 알림을 받는 객체들의 참조값만 저장하고 있다가 알림을 줘야하는 상황인 경우, notifyObservers 함수를 호출만 하면 된다.
알림 받는 클래스
interface Observer {
fun update(message: String) : String
}
class Customer(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "일반 고객 $name: $message"
}
}
class VipCustomer(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "VIP 고객 $name: 우선 알림 - $message"
}
}
class Admin(
private val name: String
) : Observer {
override fun update(message: String) : String {
return "관리자 $name: 입고 내역 기록 - $message"
}
}
- 알림에 대한 구체적인 구현도 클래스 단위로 다르게 구현한다.
- 알림을 주는 클래스안에는 알림을 주긴 주는데 이에대한 구체적 내용은 알림을 받는 클래스가 직접 구현해서 나름의 차등화를 시키는 것도 있다. 물론 이부분은 Observer 패턴의 핵심은 아니다.
kotest 코드
class ObserverPatternTest : DescribeSpec({
describe("Store의 notifyObservers()") {
context("일반 고객, VIP 고객, 관리자가 구독한 상태에서 알림을 보내면") {
val store = Store()
val john = Customer("John")
val kali = Customer("Kali")
val jane = VipCustomer("Jane")
val manager = Admin("Mike")
store.subscribe(john)
store.subscribe(jane)
store.subscribe(manager)
val result = store.notifyObservers("RTX 5070이 입고되었습니다.")
it("각 Observer가 자신의 방식으로 메시지를 출력한다") {
result shouldBe listOf(
"일반 고객 John: RTX 5070이 입고되었습니다.",
"VIP 고객 Jane: 우선 알림 - RTX 5070이 입고되었습니다.",
"관리자 Mike: 입고 내역 기록 - RTX 5070이 입고되었습니다."
)
}
}
}
})
- 여기서 보면 john 이랑 jane 고객은 알림을 받겠다고 하여(가정) store.subscribe(john), store.subscribe(jane) 만을 추가하여 Store 라는 알림 관리 클래스 객체안에 john 과 jane 고객 객체 참조값만을 저장하기만 하고 알림있을때마다 알림 method인 notifyObservers() 만 호출하면 된다.
- 그리고 Kali 라는 이름을 가진 고객은 store.subscribe() 라는 method를 호출하지만 않으면 알림을 굳이 받지 않는 객체로서 존재할 수 있다.
'Backend' 카테고리의 다른 글
| TemplateMethod Pattern (0) | 2026.08.03 |
|---|---|
| Singleton Pattern (0) | 2026.08.03 |
| Builder Pattern (0) | 2026.08.01 |
| FactoryMethod Pattern (0) | 2026.07.30 |
| UnitTest (0) | 2026.07.06 |
