신문사 + 구독자 = 옵저버 패턴
신문 구독 메커니즘만 제대로 이해할 수 있다면 옵저버 패턴을 쉽게 이해할 수 있습니다.
신부사를 주제(subject), 구독자를 옵저버(observer)라고 부른다는 것만 외워 두세요.
옵저버 패턴(Observer Pattern)은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에 연락이 가고
자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의합니다.
옵저버 패턴은 여러 가지 방법으로 구현할 수 있지만, 보통은 주제 인터페이스와 옵저버 인터페이스가 들어있는 클래스 디자인으로 구현합니다.
아뇨, 관계가 있긴 하지만 같진 않아요. 출판-구독 패턴은 구독자가 서로 다른 유형의 메시지에 관심을 가질 수 있고,
출판사와 구독자를 더 세세하게 분리할 수 있는 복잡한 패턴입니다. 미들웨어 시스템에서 종종 쓰입니다.
느슨한 결합(Loose Coupling)은 객체들이 상호작용할 수는 있지만 서로를 잘 모르는 관계를 의미합니다.
옵저버 패턴은 느슨한 결합을 보여주는 훌륭한 예입니다. 옵저버 패턴에서 어떤 식으로 느슨한 결합을 만드는지 알아볼까요?
디자인 원칙 - 상호작용하는 객체 사이에는 가능하면 느슨한 결합을 사용해야 한다.
아, 좋은 질문입니다. 자바에는 옵저버 패턴용 Observable 클래스와 Observer 인터페이스가 있었죠.
Observable 클래스는 수이가 직접 코드를 작성하지 않아도 옵저버를 추가하고 삭제하고 옵저버에 알림을 보내는 메소드를 제공했습니다.
Observer 인터페이스는 update() 메소드를 포함하여 앞에서 우리가 만든것과 유사한 인터페이스를 제공했죠.
이 클래스들은 자바 9 이후로는 쓰이지 않습니다.
각자 자신의 코드에서 기본적인 옵저버 패턴을 지원하는 게 더 편하다고 생각하는 사람들과
더 강력한 기능을 스스로 구현하는게 낫겠다고 생각하는 사람들이 늘어나면서 Observer와 Observable은 역사의 뒤안길로 사라지고 말았습니다.
자바빈은 Bean에서 PropertyChangeEvents로 유형 속성이 바뀌었을 때 PropertyChangeListener에 알림을 보내 주는 기능을 제공합니다.
또한 비동기 스트림을 처리하는 Flow API와 관련된 출판-구독 구성 요소도 제공합니다.
Observer를 알림 순서에 의존하지 말라는 JDK 권고가 있습니다.
푸시를 풀로 바꾸는건 정말 좋은 생각입니다.
아까 방구석 토크에서 주제와 옵저버가 푸시(주제가 옵저버에게 상태를 알리는 방식)와 풀(옵저버가 주제로부터 상태를 끌어오는 방식을) 가지고 토론했던 걸 다시 생각해 봤어요.
디스플레이가 WeatherData 객체로부터 필요할 때마다 데이터를 끌어오면 코드를 조금 더 일반화할 수 있지 않나요? 그러면 나중에 새로운 디스플레이를 추가하기도 더 쉬울 것 같은데요?
지금 만들어놓은 WeatherData 디자인은 하나의 데이터만 갱신해도 되는 상황에서도 update() 메소드에 모든 데이터를 보내도록 되어 있습니다.
그래도 별문제는 없지만, 나중에 Weather-O-Rama에서 풍속 같은 새로운 데이터 값을 추가한다면 어떨까요?
대부분의 update() 메소드에서 풍속 데이터를 쓰지 않더라도 모든 디스플레이에 있는 update() 메소드를 바꿔야 하지 않을까요?
사실 푸시를 사용하거나 풀을 사용하는 방법중 어느 하나를 선택하는 일은 구현 방법의 문제라고 볼 수 있습니다.
하지만 대체로 옵저버가 필요한 데이터를 골라서 가져가도록 만드는 방법이 더 좋습니다.
시간이 지남에 따라 애플리케이션은 계속 바뀌고 점점 더 복잡해집니다.
실제로 CEO인 조니 허리케인은 기상 스테이션을 확장해서 더 많은 디스플레이를 팔고 싶어 합니다.
그러니 나중에 더 쉽게 확장할 수 있도록 디자인을 다시 한번 살펴봐야 합니다.
옵저버가 필요한 데이터를 당겨올 수 있도록 기상 스테이션 코드를 수정하는 일은 그리 어렵지 않습니다.
주제가 자신의 데이터에 관한 getter 메소드를 가지게 만들고 필요한 데이터를 당겨올 때 해당 메소드를 호출할 수 있도록 옵저버를 고쳐 주기만 하면 됩니다.
지금은 주제 데이터가 바뀌면 update()를 호출해서 옵저버에 새로운 온도, 습도, 기압 데이터를 보냅니다.
값이 변했다는 알림을 옵저버가 받았을 때 주제에 있는 게터 메소드를 호출해서 필요한 값을 당겨오도록 만들어 봅시다.
풀 방식으로 바꾸려면 기존 코드를 살짝 고쳐야 합니다.