# 옵저버 패턴
먼저 책에서 나온 옵저버 패턴의 정의를 살펴보자!
한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다
한줄로 정리 하자면 일련의 객체 사이에서 일대다 관계를 정의 한다라고 보면 된다.
책에서는 기상 정보를 예를 들었다 나는 주식 가격 변동 모니터링 서비스으로 예를들겠다.
시장에서 주식의 가격이 변하면 이 정보를 받아서 각각의 투자자에게 알려주는 시스템이라고 치겠다.
우선 옵저버 패턴은 일대다라고 했으니 주식이 일에 해당하고 그 주식 투자자가 다에 해당한다고 보면 된다.
주식 가격 변동 모니터링 서비스를 옵저버 패턴으로 구현하면
- 주식 가격이 변하면 거기에 의존하는 모든 투자자들한테 알림이 간다.
위와 같은 시나리오가 나올 것 이다.
옵저버 패턴의 예제 코드를 보기 전에 책에서는 느슨한 결합을 설명해주기 때문에 이부분도 정리 하고 넘어 가면 좋을 것 같다.
# 느슨한 결합(Loose Coupling)이란?
객체들이 상호작용할 수는 있지만, 서로를 잘 모르는 관계를 의미한다.
위에서 나온 정의는 책에서 나온 정의이다.
## 느슨한 결합을 왜 사용해야 할까?

위에 사진은 강한 결합으로 클래스를 구성했을때 상황을 보여준다.
이 경우 ClassA에 변동이 생기면 ClassB,C,D 전부 영향을 끼치는 현상이 일어난다.
만약 Class가 100개 1000개 있다면? 영향을 끼치는 부분이 어마어마하게 늘어난다.

이번에는 느슨한 결합으로 클래스를 구성했을시 위 사진처럼 된다 보기에도 확실히 간단해진걸 느낄 수 있다.
책에서는 느슨한 결합을 사용하는 이유는 아래와 같이 말하고 있다.
변경 사항이 생겨도 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있다.
객체 사이의 상호의존성을 최소화 할 수 있기 때문
# 예제 코드
이제 코드로 패턴을 차근 차근 만들어보자!
## 인터페이스 만들기
### 옵저버 인터페이스
- 모든 옵저버 클래스에서 구현해야하는 인터페이스
- 모든 옵저버는 인터페이스안에 있는 메소드를 구현해야함
interface StockObserver {
// 주식 정보가 변경 되었을때 옵저버에게 이름과 가격이 전달 됨
fun update(stockName: String, price: Double)
}
### 주제(Subject) 인터페이스
- 옵저버를 등록, 제거하는 메서드와 주제에 상태가 변경되었을 때 모든 옵저버에게 알림을 보내는 메서드를 생성해준다.
interface StockSubject {
fun register(observer: StockObserver)
fun unregister(observer: StockObserver)
fun notifyObservers(stockName: String, price: Double)
}
## 인터페이스를 구현하는 클래스 만들기
### 주식 거래자 클래스
- 가격 변동을 확인하기 위해 위에서 만들어 준 StockObserver를 상속 받아야한다.
- printPrice 메서드를 통해 출력
class StockTrader(val name: String): StockObserver {
private var stockName: String = ""
private var price: Double = 0.0
override fun update(stockName: String, price: Double) {
this.stockSymbol = stockSymbol
this.price = price
printPrice()
}
private fun printPrice() {
println("현재 유저 이름 : $name")
println("가격 업데이트: $stockName = $price")
}
}
### 주식 시장 클래스
- 위에서 만들어준 StockSubject 인터페이스를 상속 받아야한다.
- 옵저버를 등록하거나 제거하는 역할과 변동을 모든 옵저버들한테 알려주는 역할을 한다.
class StockMarket: StockExchange {
private val observers: MutableList<StockObserver> = mutableListOf()
// override를 통해 옵저버를 등록하는 메서드
override fun register(observer: StockObserver) {
observers.add(observer)
}
// override를 통해 옵저버를 삭제하는 메서드
override fun unregister(observer: StockObserver) {
observers.remove(observer)
}
// 갱신된 값을 받고 notifyObservers메서드를 호출한다
fun setPrice(stockSymbol: String, price: Double) {
notifyObservers(stockSymbol, price)
}
// 갱신된 값을 모든 옵저버들한테 알린다
override fun notifyObservers(stockSymbol: String, price: Double) {
for (observer in observers) {
observer.update(stockSymbol, price)
}
}
}
## 메인 클래스 구현
- 주식 거래소를 만든다.
- 주식 거래자를 생성해준다.
- 주식 거래소에 주식 거래자를 등록한다.(옵저버 등록)
- 주식 가격이 변동되었다고 알린다.
- 주식 거래소에서 주식 거래자 중 한명을 제거 한다. (옵저버 제거)
- 다시 주식 가격 변동을 알린다. (위에서 제외한 주식 거래자는 알림이 안 가야한다.)
fun main() {
// 1.주식 거래소 생성
val stockMarket = StockMarket()
// 2.주식 거래자 생성
val user1 = StockTrader("유저1")
val user2 = StockTrader("유저2")
// 3.주식 거래소에 주식 거래자 등록
stockMarket.register(user1)
stockMarket.register(user2)
// 4.주식 가격 변동 알림
stockMarket.setPrice("삼성전자", 55000.0)
stockMarket.setPrice("테슬라", 75000.0)
// 5.주식 거래소에서 user1 주식 거래자 제거
stockMarket.unregister(user1)
// 6.주식 가격 변동 알림(user1 알림 받지 않음)
stockMarket.setPrice("삼성전자", 57000.0)
}
## 결과

# 느낀점
- 평소에 안드로이드에서는 livedata로 자동으로 옵저빙을 해줘서 옵저버 패턴이 정확히 어떤 식으로 작동하는지 모르고 사용했는데 이번 기회에 전부는 아니지만 어느 정도는 알고 가서 좋은 거 같다!
출처 작가 Racool_studio 출처 Freepik https://medium.com/@hyunhoshinKR/1%EB%B6%84-%EB%A7%8C%EC%97%90-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EB%8A%90%EC%8A%A8%ED%95%9C-%EA%B2%B0%ED%95%A9-%EC%9B%90%EC%B9%99-d5ce477ca490