티스토리 뷰
옵저버 패턴
옵저버 패턴(Observer Pattern)이란, GoF가 소개한 디자인 패턴 중 하나로 관찰 대상이 되는 객체가 변경되면 대상 객체를 관찰하고 있는 옵저버(observer)에게 변경사항을 통지(notify)하는 디자인 패턴을 말한다. 옵저버 패턴을 사용하면 객체 간의 상호작용을 수월하게 하고 효과적으로 데이터를 전달할 수 있다.
옵저버 패턴 구조
- 옵저버 패턴은 관찰 대상인
서브젝트(Subject)
와 이를 관찰하는옵저버(Observer)
로 이루어져 있다. - 하나의 서브젝트에는 1개 또는 여러 개의 옵저버를 등록할 수 있다.
- 서브젝트의 상태가 변경되면 자신을 관찰하는 옵저버들에게 변경사항을 통지한다.
- 서브젝트로 변경사항을 통지 받은 옵저버는 부가적인 처리를 한다.
- 옵저버 패턴은 서브젝트와 옵저버를 상속하는
구체화(Concreate)
클래스가 존재한다. - 구체화 클래스는 서브젝트와 옵저버에 대한 상세 구현을 작성한다.
Subject Function
- add : 서브젝트의 상태를 관찰할 옵저버를 등록한다.
- remove : 등록된 옵저버를 삭제한다.
- notify : 서브젝트 상태가 변경되면 등록된 옵저버에 통지한다.
Observer Function
- update : 서브젝트의 notify 내부에서 호출되며, 서브젝트의 변경에 따른 부가 기능을 처리한다.
옵저버 패턴 예제 코드
class Coffee(val name: String)
// Subject
class Barista : Observable() {
private lateinit var coffeeName: String
fun orderCoffee(name: String) {
this.coffeeName = name
}
fun makeCoffee() {
setChanged()
notifyObservers(Coffee(this.coffeeName))
}
}
// Observer
class Customer(val name: String) : Observer {
override fun update(o: Observable?, arg: Any?) {
val coffee = arg as Coffee
println("${name}이 ${coffee.name}를 받았습니다.")
}
}
fun main() {
val barista = Barista()
barista.orderCoffee("아이스 아메리카노")
val customer1 = Customer("고객1")
val customer2 = Customer("고객2")
val customer3 = Customer("고객3")
barista.addObserver(customer1)
barista.addObserver(customer2)
barista.addObserver(customer3)
barista.makeCoffee()
}
- Customer 클래스는 Observer 인터페이스를 구현하여 Barista 클래스가 커피를 완성하면 통지를 받아서 update 함수에서 처리한다.
- Barista 클래스는 Observable 클래스를 상속하여 고객이 주문한 커피가 만들어지면 notifyObserver로 고객에게 만들어진 Coffee 객체를 전달한다. 이때 setChanged를 먼저 호출하여 변경 여부를 내부에 저장한다.
- Customer 클래스가 Barista 클래스를 관찰하기 위해 addObserver로 등록한다.
옵저버 패턴의 장점
- 옵저버 패턴을 사용하지 않았다면 고객은 일정 간격으로 커피가 완성됐는지 바리스타에게 확인하는 처리가 있어야 한다.
- 간격이 너무 짧으면 변경된 상태를 빠르게 확인할 수 있지만 매번 불필요한 호출이 발생하므로 성능상 문제가 발생할 수 있고, 간격이 너무 길면 변경된 상태를 즉시 확인할 수 없으므로 실시간성이 떨어지게 된다.
- 옵저버 패턴은 관찰자인 옵저버가 서브젝트의 변화에 신경쓰지 않고, 상태 변경의 주체인 서브젝트가 변경사항을 옵저버에게 알려줌으로써 앞서 언급한 문제를 해결할 수 있다.
- 옵저버 패턴은 데이터를 제공하는 측에서 데이터를 소비하는 측에 통지하는
Push-Based
이다.
이터레이터 패턴
이터레이터 패턴(Iterator Pattern)은 데이터의 집합에서 데이터를 순차적으로 꺼내기 위해 만들어진 디자인 패턴을 말한다. 이터레이터 패턴을 사용하면 컬렉션이 변경되더라도 동일한 인터페이스를 사용해 데이터를 꺼내올 수 있기 때문에 변경사항 없이 사용할 수 있다. 데이터의 집합이 얼만큼의 크기를 가졌는지 알 수 없는 경우, 이터레이터 패턴을 사용하면 순차적으로 데이터를 꺼내올 수 있다.
- 애그리게잇(Aggregate)은 요소들의 집합체를 나타낸다.
- 이터레이터는 집합체 내부에 구현된 iterator를 이용해 생성한다.
- 이터레이터를 사용하는 클라이언트는
hasNext
함수를 사용해 데이터가 존재하는지 검사하고,next
함수를 사용해 데이터를 꺼낸다.
이터레이터 패턴 예제 코드
data class Car(val brand: String)
class CarIterable(
val cars: List<Car> = listOf()
) : Iterable<Car> {
override fun iterator(): Iterator<Car> = CarIterator(cars)
}
class CarIterator(
val cars: List<Car> = listOf(),
var index: Int = 0
) : Iterator<Car> {
override fun hasNext(): Boolean = cars.size > index
override fun next(): Car = cars[index++]
}
fun main() {
val carIterable = CarIterable(listOf(Car("페라리"), Car("포르쉐"), Car("BMW")))
val iterator = carIterable.iterator()
while (iterator.hasNext()) {
println("Brand : ${iterator.next()}")
}
}
- CarIterator 클래스는 Iterable 인터페이스를 구현하여 CarsIterator를 생성하는 Iterator 함수를 오버라이드한다.
- CarIterator 클래스는 Iterator 인터페이스를 구현하여 데이터가 존재하는지 확인하는 hasNext, 데이터가 존재하면 가져오는 next 함수를 오버라이드한다.
- while문 내부에선 hasNext를 사용하여 데이터를 모두 가져올때까지 반복하고 데이터를 출력한다.
옵저버 패턴과 차이점
- 데이터를 제공한다는 관점에서 이터레이터 패턴과 옵저버 패턴은 유사하다.
- 이터레이터 패턴은 애그리게잇(Aggregate)이 내부에 데이터를 저장하고 이터레이터를 사용해 데이터를 순차적으로 당겨오는 방식이기 때문에
Pull-Based
이다.
'Study' 카테고리의 다른 글
[운영체제] 멀티태스킹과 멀티프로세싱 & 프로세스와 스레드 (2) | 2024.08.07 |
---|---|
[AWS] Solution Architect Associate(SAA-C03) 취득 (1) | 2023.06.12 |
[데이터베이스] RDB와 NoSQL의 차이는? (0) | 2022.08.24 |
[운영체제] 가상 메모리 (Virtual Memory) (0) | 2022.08.22 |
[운영체제] 메모리 관리 기법 - 페이징 & 세그멘테이션 (0) | 2022.08.21 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 데이터베이스
- 북클럽
- kotlin
- 노마드
- MySQL
- webflux
- spring boot
- 그리디
- Spring
- 노마드코더
- 스프링부트
- 스프링 부트
- 인프런
- 리팩토링
- 코테
- leetcode
- 정렬
- 김영한
- 알고리즘
- 문자열
- 파이썬
- 자료구조
- Algorithm
- 구현
- 코틀린
- Real MySQL
- mysql 8.0
- 릿코드
- 백준
- 스프링
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 30 | 31 |
글 보관함